Java 弱引用持有的类加载器?
我一直在与一些内存泄漏作斗争,目前我对这个问题感到困惑。有一个web应用程序类加载器应该被垃圾收集,但它不是(即使在我修复了几个漏洞之后)。我用jmap转储了堆,用jhat浏览了堆,找到了类加载器并检查了根集引用 如果排除弱引用,则列表为空!既然只由弱引用持有的对象应该被垃圾回收,这怎么可能呢?(我在jconsole中多次执行GC) 如果我包括弱引用,我会得到一个引用列表,所有引用都来自以下字段之一:Java 弱引用持有的类加载器?,java,memory-leaks,garbage-collection,classloader,Java,Memory Leaks,Garbage Collection,Classloader,我一直在与一些内存泄漏作斗争,目前我对这个问题感到困惑。有一个web应用程序类加载器应该被垃圾收集,但它不是(即使在我修复了几个漏洞之后)。我用jmap转储了堆,用jhat浏览了堆,找到了类加载器并检查了根集引用 如果排除弱引用,则列表为空!既然只由弱引用持有的对象应该被垃圾回收,这怎么可能呢?(我在jconsole中多次执行GC) 如果我包括弱引用,我会得到一个引用列表,所有引用都来自以下字段之一: java.lang.reflect.Proxy.loaderToCache java.lan
- java.lang.reflect.Proxy.loaderToCache
- java.lang.reflect.Proxy.ProxyClass
- java.io.ObjectStreamClass$Caches.localDescs
- java.io.ObjectStreamClass$Caches.reflector
- java.lang.ref.Finalizer.unfinalized
- 提供支持您的声明的权威文章的链接
- 提供一个示例程序来演示该行为
我真的很想弄清这件事的真相。实际上,我花了一些精力在测试程序中重现这个问题,但我失败了——每次都会在System.gc()上立即收集类加载器,除非有对它的强引用。类驻留在特殊内存空间中-永久生成。卸载类加载器。GC应该选择将perm空间包含到集合的范围中。不同的GC算法有一些不同的行为,但一般来说,GC会尽量避免perm空间收集
根据我的经验,即使类加载器不可访问,JVM在尝试收集PERM空间之前也可能会出现OutOfMemoryError 似乎在某个地方涉及到了软引用。这是我能找到的关于延迟收集(大约40分钟)的唯一解释。我最初以为软引用会一直保留到内存耗尽,但我发现事实并非如此 From:“软访问对象在上次引用后的一段时间内将保持活动状态。默认值为堆中每空闲兆字节一秒的生存期。可以使用-XX:SoftRefLRUPolicyMSPerMB标志调整此值” 因此,我将该标志调整为1,并在几秒钟内收集了类加载器
我认为软引用来自ObjectStreamClass。问题是为什么jhat没有在根集引用中显示它。是因为它既不强也不弱吗?还是因为它已经从相同的静态字段中找到了弱引用?还是其他原因?不管怎样,我认为jhat中的这一点需要改进。那么你的问题在哪里呢?你试过Java 7 update 40吗?如果它是一个bug,它可能已经被修复了。@isnot2bad做了所有你认为正常的事情@PeterLawrey目前正在使用icedtea 6.1.12.6,我将尝试第7版later@PeterLawrey我刚刚试过使用icedtea 7.2.4.3,同样的情况也发生了,唯一的区别是com.sun.beans.TypeResolver.CACHE中还有一个弱引用。我还没有等待40多分钟,看看它是否最终收集了类加载器。请参阅我添加到问题中的注释。我怀疑
jhat
未命中它的原因是ObjectStreamClass.class
无法通过classloader.class
访问,因为它位于引导类路径中。换句话说,JRE类中静态字段持有的任何引用都将丢失。