Java 无法访问的对象不会从堆中进行垃圾收集

Java 无法访问的对象不会从堆中进行垃圾收集,java,tomcat,garbage-collection,jvm,heap,Java,Tomcat,Garbage Collection,Jvm,Heap,我正在努力处理JVM堆(Java1.7)中无法访问的对象。正如您从图片中看到的(图片上的所有类都是不可访问的),我们有超过74%的对象没有引用,因此应该将其收集起来。在我们的tomcat 7服务器上运行3周后,这种状态就会变为只运行探测监控应用程序、tomcat manager和我们的webapp,这可能是问题的根源 我们的应用程序基于JSF 1.2,在客户端上保存状态,这是您在下图中看到的,主要是ViewSaveState的字符数组。 当我从jVisualVM手动运行GC时,它会删除所有无法访

我正在努力处理JVM堆(Java1.7)中无法访问的对象。正如您从图片中看到的(图片上的所有类都是不可访问的),我们有超过74%的对象没有引用,因此应该将其收集起来。在我们的tomcat 7服务器上运行3周后,这种状态就会变为只运行探测监控应用程序、tomcat manager和我们的webapp,这可能是问题的根源

我们的应用程序基于JSF 1.2,在客户端上保存状态,这是您在下图中看到的,主要是ViewSaveState的字符数组。 当我从jVisualVM手动运行GC时,它会删除所有无法访问的对象,并且在堆达到极限的3周之前一切都正常

有些物体怎么可能没有清理干净

我们的JVM参数

-Dcom.sun.management.jmxremote=true
-Dcom.sun.management.jmxremote.port=29001
-Dcom.sun.management.jmxremote.authenticate=false
-Dcom.sun.management.jmxremote.ssl=false
-Djava.rmi.server.hostname=
-Dorg.apache.el.parser.SKIP_IDENTIFIER_CHECK=true
-Xms320m
-Xmx2500m
-XX:MaxPermSize=500m
-XX:PermSize=96m
-verbose:gc
-Xloggc:/var/log/gc.log
-XX:+PrintGCTimeStamps
-XX:+PrintGCDetails
-Xdebug -Xrunjdwp:transport=dt_socket,address=1044,server=y,suspend=n
-XX:+CMSClassUnloadingEnabled -XX:+UseConcMarkSweepGC

OutOfMemoryError的堆栈跟踪

我认为原因隐藏在其他地方,stacktraces来自应用程序的不同部分。可能存在一些泄漏,但stacktraces只报告最后一个组件,该组件在没有内存时及时占用了一些内存

    java.lang.OutOfMemoryError: Java heap space
            at java.util.LinkedHashMap.createEntry(LinkedHashMap.java:442)
            at java.util.HashMap.addEntry(HashMap.java:888)
            at java.util.LinkedHashMap.addEntry(LinkedHashMap.java:427)
            at java.util.HashMap.put(HashMap.java:509)
            at sun.util.resources.OpenListResourceBundle.loadLookup(OpenListResourceBundle.java:134)
            at sun.util.resources.OpenListResourceBundle.loadLookupTablesIfNecessary(OpenListResourceBundle.java:113)
            at sun.util.resources.OpenListResourceBundle.handleGetObject(OpenListResourceBundle.java:74)
            at sun.util.resources.TimeZoneNamesBundle.handleGetObject(TimeZoneNamesBundle.java:75)
            at java.util.ResourceBundle.getObject(ResourceBundle.java:389)
            at java.util.ResourceBundle.getObject(ResourceBundle.java:392)
------------------
Exception in thread "Timer-22" Exception in thread "com.mchange.v2.async.ThreadPoolAsynchronousRunner$PoolThread-#2" java.lang.OutOfMemoryError: Java heap space
Exception in thread "com.mchange.v2.async.ThreadPoolAsynchronousRunner$PoolThread-#1" java.lang.OutOfMemoryError: Java heap space
------------------
Caused by: java.lang.OutOfMemoryError: Java heap space
        at java.util.Arrays.copyOf(Arrays.java:2219)
        at java.util.ArrayList.grow(ArrayList.java:242)
        at java.util.ArrayList.ensureExplicitCapacity(ArrayList.java:216)
        at java.util.ArrayList.ensureCapacityInternal(ArrayList.java:208)
        at java.util.ArrayList.add(ArrayList.java:440)
        at org.hibernate.loader.Loader.instanceNotYetLoaded(Loader.java:1468)
        at org.hibernate.loader.Loader.getRow(Loader.java:1355)
        at org.hibernate.loader.Loader.getRowFromResultSet(Loader.java:611)
        at org.hibernate.loader.Loader.doQuery(Loader.java:829)
        at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:274)
         at org.ajax4jsf.component.AjaxActionComponent.broadcast(AjaxActionComponent.java:55)
        at org.ajax4jsf.component.AjaxViewRoot.processEvents(AjaxViewRoot.java:329)
        at org.ajax4jsf.component.AjaxViewRoot.broadcastEventsForPhase(AjaxViewRoot.java:304)
        at org.ajax4jsf.component.AjaxViewRoot.processPhase(AjaxViewRoot.java:261)
        at org.ajax4jsf.component.AjaxViewRoot.processApplication(AjaxViewRoot.java:474)
        at org.apache.myfaces.lifecycle.InvokeApplicationExecutor.execute(InvokeApplicationExecutor.java:32)
        at org.apache.myfaces.lifecycle.LifecycleImpl.executePhase(LifecycleImpl.java:103)
        at org.apache.myfaces.lifecycle.LifecycleImpl.execute(LifecycleImpl.java:76)
        at javax.faces.webapp.FacesServlet.service(FacesServlet.java:183)
        ... 74 more
--------------
Caused by: java.lang.OutOfMemoryError: Java heap space
        at java.nio.ByteBuffer.wrap(ByteBuffer.java:350)
        at java.lang.StringCoding$StringDecoder.decode(StringCoding.java:137)
        at java.lang.StringCoding.decode(StringCoding.java:173)
        at java.lang.String.<init>(String.java:443)
        at com.ibm.db2.jcc.a.a.a(a.java:632)
        at com.ibm.db2.jcc.a.a.a(a.java:355)
        at com.ibm.db2.jcc.am.fc.e(fc.java:682)
        at com.ibm.db2.jcc.am.fc.k(fc.java:1481)
        at com.ibm.db2.jcc.am.ResultSet.getTimestampX(ResultSet.java:1075)
        at com.ibm.db2.jcc.am.ResultSet.getTimestamp(ResultSet.java:1034)
java.lang.OutOfMemoryError:java堆空间
位于java.util.LinkedHashMap.createEntry(LinkedHashMap.java:442)
在java.util.HashMap.addEntry(HashMap.java:888)
位于java.util.LinkedHashMap.addEntry(LinkedHashMap.java:427)
位于java.util.HashMap.put(HashMap.java:509)
位于sun.util.resources.OpenListResourceBundle.loadLookup(OpenListResourceBundle.java:134)
在sun.util.resources.OpenListResourceBundle.LoadLookupTablesIfRequired(OpenListResourceBundle.java:113)中
位于sun.util.resources.OpenListResourceBundle.handleGetObject(OpenListResourceBundle.java:74)
位于sun.util.resources.TimeZoneNamesBundle.handleGetObject(TimeZoneNamesBundle.java:75)
位于java.util.ResourceBundle.getObject(ResourceBundle.java:389)
位于java.util.ResourceBundle.getObject(ResourceBundle.java:392)
------------------
线程“Timer-22”中的异常线程“com.mchange.v2.async.ThreadPoolAsynchronousRunner$PoolThread-#2”java.lang.OutOfMemory中的异常错误:java堆空间
线程“com.mchange.v2.async.ThreadPoolAsynchronousRunner$PoolThread-#1”java.lang.OutOfMemoryError中出现异常:java堆空间
------------------
原因:java.lang.OutOfMemoryError:java堆空间
位于java.util.Arrays.copyOf(Arrays.java:2219)
位于java.util.ArrayList.grow(ArrayList.java:242)
在java.util.ArrayList.ensureExplicitCapacity处(ArrayList.java:216)
位于java.util.ArrayList.ensureCapacityInternal(ArrayList.java:208)
add(ArrayList.java:440)
位于org.hibernate.loader.loader.instanceNotYetLoaded(loader.java:1468)
位于org.hibernate.loader.loader.getRow(loader.java:1355)
位于org.hibernate.loader.loader.getRowFromResultSet(loader.java:611)
位于org.hibernate.loader.loader.doQuery(loader.java:829)
在org.hibernate.loader.loader.doQueryAndInitializeNonLazyCollections(loader.java:274)上
位于org.ajax4jsf.component.AjaxActionComponent.broadcast(AjaxActionComponent.java:55)
位于org.ajax4jsf.component.AjaxViewRoot.processEvents(AjaxViewRoot.java:329)
位于org.ajax4jsf.component.AjaxViewRoot.broadcastEventsForPhase(AjaxViewRoot.java:304)
位于org.ajax4jsf.component.AjaxViewRoot.processPhase(AjaxViewRoot.java:261)
位于org.ajax4jsf.component.AjaxViewRoot.processApplication(AjaxViewRoot.java:474)
位于org.apache.myfaces.lifecycle.InvokeApplicationExecutor.execute(InvokeApplicationExecutor.java:32)
位于org.apache.myfaces.lifecycle.LifecycleImpl.executePhase(LifecycleImpl.java:103)
在org.apache.myfaces.lifecycle.LifecycleImpl.execute上(LifecycleImpl.java:76)
位于javax.faces.webapp.FacesServlet.service(FacesServlet.java:183)
... 74多
--------------
原因:java.lang.OutOfMemoryError:java堆空间
位于java.nio.ByteBuffer.wrap(ByteBuffer.java:350)
在java.lang.StringCoding$StringDecoder.decode(StringCoding.java:137)
在java.lang.StringCoding.decode(StringCoding.java:173)
位于java.lang.String。(String.java:443)
位于com.ibm.db2.jcc.a.a.a(a.java:632)
在com.ibm.db2.jcc.a.a.a(a.java:355)
com.ibm.db2.jcc.am.fc.e(fc.java:682)
com.ibm.db2.jcc.am.fc.k(fc.java:1481)
位于com.ibm.db2.jcc.am.ResultSet.getTimestampX(ResultSet.java:1075)
位于com.ibm.db2.jcc.am.ResultSet.getTimestamp(ResultSet.java:1034)

您所面临的行为有几个方面。首先也是最重要的一点是,在任何给定时间都在堆中拥有无法访问的对象是完全正常的。垃圾回收将在下一次运行期间清除无法访问的对象,并将清除堆中的对象。因此,在堆转储中看到无法访问的数据结构既不是坏事,也不是异常

但是当面对java.lang.OutOfMemoryError:java堆空间错误时,这些无法访问的引用应该被清除。您可以通过在启动参数中添加-XX:+heapdumponotofmemoryError来检查这一点,在生成下一个OutOfMemoryError时触发堆转储。当您现在对这个转储进行爬网时,您不应该看到无法访问的对象,至少不应该看到任何显著大小的对象


理解了这一点之后,根本问题仍然不清楚,其中一个可能的原因肯定是堆泄漏。为此,您可以使用OutOfMemoryError继续使用JVM崩溃期间获得的相同内存转储,也可以使您的生活更轻松,并附加Java内存泄漏检测器以在源代码中找到泄漏的确切位置

这个问题可能与这个问题有关

我在AIX6.1上运行IBMJVM5时遇到了同样的问题

在两个fullgc之间保持一致增长的保留堆的唯一数量是不可访问的对象,如果我没有错的话,这些对象被标记为ROOT