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

2022-06-30 15:58:20 +08:00
 moxiaowei

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

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

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

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

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

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

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

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

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

这个对象你仍然可以通过 类.a 访问啊,怎么就内存泄露了。
moxiaowei
2022-06-30 16:21:57 +08:00
@quicksand 谢谢 我理解了
cpstar
2022-06-30 16:32:15 +08:00
这是 JVM 的内存机制问题,new A()创建了堆区,把它给 static A ,那么引用计数+1 ,内存回收的时候,看到这个引用>0 的,是不回收的,必然会在内存中一直呆着。这哪能叫内存泄漏,这叫内存占用。
chtcrack
2022-06-30 16:35:35 +08:00
帮你搜索了一下 java 内存泄漏的文章,建议你去看看..
https://developer.51cto.com/article/667083.html
hhjswf
2022-06-30 16:39:13 +08:00
内存泄漏是该回收而没法回收的。这个堆对象一直都不是回收对象啊
zmal
2022-06-30 16:46:26 +08:00
你写了 a = null ,但 new A() 对象因为某种原因未被 GC ,这才叫内存泄露。
static 属性作为 GC root ,任何时候都不会被 GC 。
pursuer
2022-06-30 18:48:17 +08:00
如果 OP 想要做动态申请释放的单例的话,可以看下弱引用
cheng6563
2022-06-30 19:12:34 +08:00
内存泄漏指的是你有这么个玩意 public static List<A> a =new ArrayList<A>();
然后你有些不知道干啥的代码一直往里面加数据,但没有任何代码去取数据或者删数据。
xFrye
2022-06-30 19:20:59 +08:00
你的类不是一直存在吗,类的生命周期跟静态变量 a 的一样,这没有 memory leak 吧
yeqizhang
2022-06-30 19:38:08 +08:00
你这种不叫内存泄露,很常见的写法了,到处都有。只是占内存而已,多了顶多会有个“内存溢出”问题
yeqizhang
2022-06-30 19:39:53 +08:00
@yeqizhang 可能也不叫内存溢出,超出内存有好几种情况
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
2022-07-13 15:52:01 +08:00
这叫内存逃逸。。。看下逃逸分析相关的知识就明白是怎么回事了,内存泄露更多的是一个过程,因为回收不掉导致可用内存随着程序运行越来越少。

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/863232

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX