Java字符串对象未及时收集垃圾
我有一个关于Java内存消耗的有趣问题。我有一个本地的C++应用程序,它调用我的java应用程序。 该应用程序基本上执行一些语言翻译\解析一些XML并响应网络请求。应用程序的大部分状态不必保留,因此它充满了接受字符串参数并返回字符串结果的方法 随着时间的推移,这个应用程序继续占用越来越多的内存,并且有一段时间它开始占用接近2GB的内存,这让我们怀疑某些哈希表或静态变量中的某个地方存在泄漏。经过仔细检查,我们没有发现任何泄漏。比较一段时间内的堆转储,可以看出char[]和String对象占用了大量内存 然而,当我们检查这些char[]字符串时,我们发现它们没有GC根,这意味着它们不应该是泄漏的原因。由于它们是堆的一部分,这意味着它们正在等待垃圾被收集。在使用了各种工具MAT\VisualVM\JHat并滚动浏览了大量此类对象之后,我使用了yourkit的试用版。Yourkit直接给出数据,表示96%的char[]和String是不可访问的。这意味着在获取转储时,堆中96%的字符串正在等待垃圾回收 我知道GC的运行很节省,但是当你通过VisualVM检查时,你可以看到它在运行:-(为什么堆上总是有这么多未使用的对象呢 IMO此应用程序占用的内存不应超过400-500 MB,这是它在前24小时停留的位置,但会继续增加堆:-( 我正在运行Java1.6.0-25Java字符串对象未及时收集垃圾,java,memory-management,memory-leaks,garbage-collection,Java,Memory Management,Memory Leaks,Garbage Collection,我有一个关于Java内存消耗的有趣问题。我有一个本地的C++应用程序,它调用我的java应用程序。 该应用程序基本上执行一些语言翻译\解析一些XML并响应网络请求。应用程序的大部分状态不必保留,因此它充满了接受字符串参数并返回字符串结果的方法 随着时间的推移,这个应用程序继续占用越来越多的内存,并且有一段时间它开始占用接近2GB的内存,这让我们怀疑某些哈希表或静态变量中的某个地方存在泄漏。经过仔细检查,我们没有发现任何泄漏。比较一段时间内的堆转储,可以看出char[]和String对象占用了大量
感谢您的帮助。尝试将堆大小减小到500 MB,看看软件是否会开始垃圾收集或消亡。Java对使用提供给它的内存并不太挑剔。您还可以研究GC调优选项,这将使GC在清理内容时更加谨慎
String reallyLongString = "this is a really long String";
String tinyString = reallyLongString.substring(2, 3);
reallyLongString = null
在上述情况下,JVM无法收集为长字符串分配的内存,因为有一个对它的一部分的引用。
如果你在用字符串做事情,而你正遭受记忆问题的折磨,这可能是你悲伤的原因
使用
tinyString=newstring(reallyLongString.substring(2,3);
取而代之。Java在你认为它是/应该是时不使用GC:-)GC是一个太复杂的主题,如果不花几周的时间真正深入研究细节,就无法理解正在发生的事情。因此,如果你看到无法解释的行为,这并不意味着它已经崩溃
你所看到的有几个原因:
System.GC()的调用
您的问题可能会消失可能根本不存在泄漏-如果
字符串
是可访问的,则可能存在泄漏。如果您为应用程序分配了多达2GB的内存,则在接近该限制之前,垃圾收集器没有理由开始释放内存。如果您不希望占用的内存超过500MB,则在以下情况下传递-Xmx 512m
启动JVM
您还可以尝试更早地开始清理。首先,不要再担心那些字符串和字符[]。在我分析过的几乎所有java应用程序中,它们都位于内存消耗列表的顶部。在这些java应用程序中,几乎没有一个是真正的问题 如果您还没有收到OutOfMemoryError,但确实担心2GB对于java进程来说太多,那么请尝试减少传递给它的Xmx值。如果它在512m或1g下运行良好,那么问题就解决了,不是吗
如果您得到OOM,那么您可以尝试的另一个选项是在java进程中使用。这是内存泄漏发现工具,它可以帮助您确定是否确实存在内存泄漏。您正在运行什么JVM?您的JVM运行时参数是什么?尝试使用
-verbose:gc
JVM标志运行应用程序,并粘贴所有额外的输出。Sky,I更新了问题本身中的JVM。我们只需在调用JVM时传递Xms,而不传递任何其他内容。如果它实际持有引用,则您会将其视为指向GC根的路径。此外,substring()方法已经复制了字符串。@StevenSchlansker:string.substring()
不会复制任何内容。它重用