关于 JVM Class被回收卸载的问题?
问题的背景是我看到了这篇文章:
https://zhuanlan.zhihu.com/p/146410261
提到
强引用链: thread -> threadLocalMap -> counter -> MyCounter.class -> WebappClassLocader ,导致WebappClassLoader泄漏。
对这个有疑问。
Class类型被卸载的条件
疑问点是
其中第二点: 加载该类的类加载被回收,是指 类加载器对象被gc。
假设MyCounter.class 由 WebAppClassLoader加载,那么 通过MyCounter.class.getClassLoader() 就可以得到WebAppClassLoader, 而WebAppClalssLoader 被gc的条件必然是没有任何人引用她,
所以 如何做到MyCounter.class 不会引用WebAppClassLoader? 否则是不是 就会出现 WebAppClassLoader一直被MyCounter.class所引用呢?
如果一直被引用的话那么WebAppClassLoader对象就不会被gc,那么MyCounter.class对象自然也不会被gc了。
感觉是鸡生蛋蛋生鸡的问题。
如果说 MyCounter.class 对 WebAppClassLoader对象有强引用, WebAppClassLoader对象又怎么可能会被回收呢。如果WebAppClassLoader对象不被gc,那么MyCOunter.class又怎么会被回收呢?
b
回答:
我梳理了一下,你现在的问题不是在探讨为什么threadLocal在tomcat中造成了内存泄露,而是只考虑类加载器与类的互引用让你觉得它们无法被卸载对吧
"WebAppClalssLoader 被gc的条件必然是没有任何人引用"
这是准确的吗?假设内存中有一对相互引用的对象,但是他们都没有任何其他的对象所引用,难道JVM就无法回收他们吗?
在不同的GC算法里对这种情况应该都是有所处理的,比如标记清除算法等等,尽管有相互引用,但是由于没有从根对象到达它们的路径,所以还是有可能被回收的。这是回答你的问题。
另外,这篇知乎文章的观点我也不是很认同。使用threadLocal时必须注意线程在threadLocal内持有的对象是否能回收。他的情况是认为通过tomcat对web应用进行reload之后就可以不管不顾了,殊不知他的程序根本没有正确地结束所有的线程,进而线程在threadLocal内持有的对象无法被回收,进而导致整个应用无法被回收。他的内存泄露是reload时不能彻底关闭之前的应用导致的
回答:
可以了解下可达性算法的分析:GCROOT和三色标记法
以上是 关于 JVM Class被回收卸载的问题? 的全部内容, 来源链接: utcz.com/p/945464.html