V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
moxiaowei
V2EX  ›  Java

关于 Java 内存泄露的问题,请各位大佬帮我看看

  •  
  •   moxiaowei · 2022-06-30 15:58:20 +08:00 · 2790 次点击
    这是一个创建于 875 天前的主题,其中的信息可能已经有所发展或是发生改变。

    现在有一个类,这个类有一个静态属性,长这样:public static A a =new A(); 那么现在来分析,new A()肯定是进 JVM 的堆区,static A a 肯定是进方法区,然后 "=" 是把方法区的 a 与堆区的数据进行一个强引用关联。那么问题来了,方法区的数据一般不会被清理掉(特殊情况除外),那么指向堆内存的数据就会一直在堆中存在,这不就是内存泄露了么?

    20 条回复    2022-07-13 15:52:01 +08:00
    7911364440
        1
    7911364440  
       2022-06-30 16:03:58 +08:00
    不算内存泄漏吧,我的理解是如果 A a 被清理掉之后,new A()没有被清理掉才算内存泄露
    chtcrack
        2
    chtcrack  
       2022-06-30 16:06:24 +08:00
    你 new 出来的不用得销毁啊,否则肯定内存泄漏,c/c++是这样的,java 不知道,原理应该差不多吧.
    Jooooooooo
        3
    Jooooooooo  
       2022-06-30 16:08:26 +08:00
    你想讨论的问题是, 什么叫做"内存泄露"

    你描述的场景, 按照通常的理解, 不是"内存泄露"

    当然, 如果你把你所描述的场景圈起来, 并且把它算成"内存泄露"的定义范围, 那它就是"内存泄露", 但很明显这样的回答你不能满意

    所以若是你想解决定义问题, 那这个意义不大

    如果你想解决的是因为这种写法导致内存越来越大的问题, 那就把具体的场景拿出来具体讨论
    AoEiuV020CN
        4
    AoEiuV020CN  
       2022-06-30 16:09:10 +08:00
    这个 a 永远是这个 A ,确实不用了非要说泄露的话也只泄露一个 A 的空间,这点通常都是无视的,
    想要清理就在确定 a 不再使用之后来个=null 不就完事了,
    Jooooooooo
        5
    Jooooooooo  
       2022-06-30 16:11:09 +08:00
    这个就和 "1 是不是素数" 这个问题有点像

    1 为什么不是素数, 因为素数定义里面说 1 不是, 你若是把 "1 是素数"加到素数的定义里, 那 1 就是素数 (有些人确实会这么定义

    语言由大家赋予含义, 你把你描述的场景叫做"内存泄露", 那它就是(只不过有可能其他人有别的定义

    在这里, 通常的定义下, 你描述的场景不是"内存泄露" (当然又要说, 若是你把它定义成"内存泄露". 那它就是
    banmuyutian
        6
    banmuyutian  
       2022-06-30 16:12:52 +08:00
    你想想 java 进程销毁的时候这个堆还存不存在
    quicksand
        7
    quicksand  
       2022-06-30 16:14:09 +08:00
    public static A a =new A()换成 String A = new String("");我觉得就能得出结论了
    dcsuibian
        8
    dcsuibian  
       2022-06-30 16:21:02 +08:00
    wiki:
    内存泄漏(英语:memory leak )是计算机科学中的一种资源泄漏,主因是计算机程序的内存管理失当,因而失去对一段已分配内存空间的控制,程序继续占用已不再使用的内存空间,或是存储器所存储之对象无法透过执行代码而访问,令内存资源空耗。

    这个对象你仍然可以通过 类.a 访问啊,怎么就内存泄露了。
    moxiaowei
        9
    moxiaowei  
    OP
       2022-06-30 16:21:57 +08:00
    @quicksand 谢谢 我理解了
    cpstar
        10
    cpstar  
       2022-06-30 16:32:15 +08:00
    这是 JVM 的内存机制问题,new A()创建了堆区,把它给 static A ,那么引用计数+1 ,内存回收的时候,看到这个引用>0 的,是不回收的,必然会在内存中一直呆着。这哪能叫内存泄漏,这叫内存占用。
    chtcrack
        11
    chtcrack  
       2022-06-30 16:35:35 +08:00   ❤️ 1
    帮你搜索了一下 java 内存泄漏的文章,建议你去看看..
    https://developer.51cto.com/article/667083.html
    hhjswf
        12
    hhjswf  
       2022-06-30 16:39:13 +08:00
    内存泄漏是该回收而没法回收的。这个堆对象一直都不是回收对象啊
    zmal
        13
    zmal  
       2022-06-30 16:46:26 +08:00
    你写了 a = null ,但 new A() 对象因为某种原因未被 GC ,这才叫内存泄露。
    static 属性作为 GC root ,任何时候都不会被 GC 。
    pursuer
        14
    pursuer  
       2022-06-30 18:48:17 +08:00
    如果 OP 想要做动态申请释放的单例的话,可以看下弱引用
    cheng6563
        15
    cheng6563  
       2022-06-30 19:12:34 +08:00
    内存泄漏指的是你有这么个玩意 public static List<A> a =new ArrayList<A>();
    然后你有些不知道干啥的代码一直往里面加数据,但没有任何代码去取数据或者删数据。
    xFrye
        16
    xFrye  
       2022-06-30 19:20:59 +08:00
    你的类不是一直存在吗,类的生命周期跟静态变量 a 的一样,这没有 memory leak 吧
    yeqizhang
        17
    yeqizhang  
       2022-06-30 19:38:08 +08:00 via Android
    你这种不叫内存泄露,很常见的写法了,到处都有。只是占内存而已,多了顶多会有个“内存溢出”问题
    yeqizhang
        18
    yeqizhang  
       2022-06-30 19:39:53 +08:00 via Android
    @yeqizhang 可能也不叫内存溢出,超出内存有好几种情况
    FrankHB
        19
    FrankHB  
       2022-07-05 03:32:58 +08:00
    @dcsuibian @yeqizhang 这种理解是错的。
    内存泄漏指的是违反资源管理预期表现的行为,可达性判断只是其中的一个保守标准,还有其它种类的 indefinitively lost 。
    理论上,[Cl98] 提出以空间复杂度类描述内存资源泄漏。这是一种涵盖比较完全的分类。在这个意义下,没有 PTC(proper tail call) 泄漏调用栈也是一种泄漏。PTC 以上还有 evlis/sfs(safe for space)等更强的保证,不过静态语言一般会因为要求局部变量静态确定而自动满足 sfs 了。
    实际上,C++ 这样的语言在基本运行时实现中也存能在其它种类的内存泄漏,例如 libstdc++ emergency buffer 会被 valgrind 标记为 lost ;尽管维护者 Jonathon Wakely 缺乏相关了解而拒不承认这是 bug 。
    泄漏并不都是不可接受的,取决于用户和开发者的预期。所以经验上,@Jooooooooo 给出了理论上也能正确的万金油回答。
    但是用户未必那么好说话。所以经常只有应用开发者两头受气了,如果自己没个数下场可能更凄惨。说到这里,再日经鄙视一下:github.com/dart-lang/language/issues/490

    [Cl98]: https://www.researchgate.net/profile/William_Clinger/publication/2728133_Proper_Tail_Recursion_and_Space_Efficiency/links/02e7e53624927461c8000000/Proper-Tail-Recursion-and-Space-Efficiency.pdf
    Aresxue
        20
    Aresxue  
       2022-07-13 15:52:01 +08:00
    这叫内存逃逸。。。看下逃逸分析相关的知识就明白是怎么回事了,内存泄露更多的是一个过程,因为回收不掉导致可用内存随着程序运行越来越少。
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   实用小工具   ·   3331 人在线   最高记录 6679   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 24ms · UTC 04:56 · PVG 12:56 · LAX 20:56 · JFK 23:56
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.