Java应用程序中已加载类的数量可能会发生内存泄漏
我最近开始分析我使用VisualVM编写的osgi java应用程序。 我注意到的一件事是,当应用程序开始向客户端发送数据(通过JMS)时,加载类的数量开始以稳定的速度增加。 但是,堆大小和PermGen大小保持不变。 即使停止发送数据,类的数量也不会下降。 这是内存泄漏吗? 我认为是这样,因为加载的类必须存储在某个地方,但即使运行了几个小时的应用程序,堆和permgen也不会增加。
对于我的分析应用程序的屏幕截图去这里
你是否在某种程度上动态创建新类?
谢谢你的帮助。 我找出了问题所在。 在我的一个类中,我使用Jaxb创建一个XML字符串。 在这样做的过程中,JAXB使用反射来创建一个新类。
JAXBContext context = JAXBContext.newInstance(this.getClass());
所以虽然JAXBContext并没有在堆中说,但这些类已经被加载了。
我再次运行我的程序,我发现正常的高原正如我所期望的那样。
我敢打赌,你的问题与字节码生成有关。
许多库在运行时使用CGLib,BCEL,Javasist或Janino为新类生成字节码,然后从受控的类加载器加载它们。 释放这些类的唯一方法是释放对类加载器的所有引用。
由于类加载器由每个类保存,这也意味着您不应该释放对所有类的引用[1]。 你可以用一个体面的分析器来捕获这些(我使用Yourkit - 搜索多个具有相同保留大小的类加载器实例)
一个问题是JVM默认不会卸载类(原因是向后兼容 - 人们假设(错误地)静态初始化只会被执行一次,事实是每次加载类时都会执行)。启用卸载,您应该通过一些使用以下选项:
-XX:+CMSPermGenSweepingEnabled -XX:+CMSClassUnloadingEnabled
(使用JDK 1.5进行测试)
即使那样,过多的字节码生成也不是一个好主意,所以我建议你看看你的代码来找到罪魁祸首并缓存生成的类。 频繁的违规者是脚本语言,动态代理(包括由应用服务器生成的代理)或巨大的Hibernate模型(在这种情况下,你可以增加你的permgen)。
也可以看看:
您可能会发现一些热点标志可用于理解此行为,如:
这是一个很好的参考:
http://java.sun.com/javase/technologies/hotspot/vmoptions.jsp
链接地址: http://www.djcxy.com/p/19835.html上一篇: Possible Memory leak in Number of Loaded classes in Java Application
下一篇: VisualVM is unable to profile a web application on Eclipse