无法访问的对象不是从堆中收集垃圾 [英] Unreachable objects are not garbage collected from heap

查看:138
本文介绍了无法访问的对象不是从堆中收集垃圾的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在我的JVM堆(Java 1.7)中遇到了无法访问的对象。正如你从图片中可以看到的(图片上的所有课程都无法访问),我们有超过74%的对象没有参考,所以应该收集包装。这种状态在我们的tomcat 7服务器上运行了3周后才运行,其中只运行探测器监控应用程序,tomcat管理器和我们的webapp,这可能是问题的根源。



我们的应用程序是基于JSF 1.2和客户端的状态保存,这是你在下面的图片中看到的 - 主要是使用ViewSaveState的char数组。
当我从jVisualVM手动运行GC时,它将删除所有无法访问的对象,并且一切都还好,直到堆满了限制的3周时间。



这怎么可能一些对象没有清理干净?



我们的JVM params

  -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来自app的不同部分。可能会有一些泄漏,但是堆栈跟踪只报告最后一个在没有任何内存时声明内存的组件。

  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.loadLookupTablesIfNecessary(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)
------------------
Exception in在线程com.mchange.v2.async.ThreadPoolAsynchronousRunner $ PoolThread-#2中的线程Timer-22异常java.lang.OutOfMemoryError:Java堆空间
线程com.mchange.v2.async中的异常。 ThreadPoolAsynchronousRunner $ PoolThread-#1java.lang.OutOfMemoryError:Java堆空间
------------------
导致:java.lang.OutOfMemoryError :java.util.Arrays.copyOf上的Java堆空间
(Arrays.java:2219)java.util.ArrayList.grow上的
(ArrayList.java:242)$ java.util中的
.ArrayList.ensureExplicitCapacity(ArrayList.java:216)$ b $在java.util.ArrayList.ensureCapacityInternal(ArrayList.java:208)$ b $在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)
在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:7 6)
在javax.faces.webapp.FacesServlet.service(FacesServlet.java:183)
... 74 more
--------------
由java.lang.OutOfMemoryError引发:Java堆空间在java.nio.ByteBuffer.wrap处
(ByteBuffer.java:350)$在java.lang.StringCoding处的$ b $ $ StringDecoder.decode( StringCoding.java:137)
在java.lang.StringCoding.decode(StringCoding.java:173)
在java.lang.String。< init>(String.java:443)
在com.ibm.db2.jcc.aaa(a.java:632)
在com.ibm.db2.jcc.aaa(a.java:355)
在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。
at com.ibm.db2.jcc.am.ResultSet.getTimestamp(ResultSet.java:1034)
jcc.am.ResultSet.getTimestampX(ResultSet.java:1075)

解决方案

一种可能性是您在 finalize() 方法。如果您的类有重载 Object.finalize()的类,那么JVM必须执行令人惊讶的工作量才能真正清理它们(并且依次清理所有他们的引用对象)。如果您创建这些对象的速度比垃圾收集器可以处理它们的速度快,那么您很快就会遇到麻烦。



本文将介绍 pathological finalizer example 详细介绍,但总结如下:


  1. 具有 finalize()方法的对象超出范围,并且(概念上)变为符合GC的条件。 一个可以简单释放的普通对象,JVM通过 Finalizer ,以防止这些对象被微不足道地收集。即使是短命的对象也能在最初的GC中存活下来,并且如果与 finalize()相关联,则会移入堆中寿命更长的部分。 >现在这些对象将被专用的 Finalizer 线程处理,该线程将在每个对象中调用 .finalize()转。尽管它们无法访问,但尚未轮到的对象仍保留在堆上。

  2. 一旦对象由 Finalizer处理线程删除最后一个引用,最终实际上可以对该GC进行GC操作。由于对象在一轮或多轮收集后仍然存在,GC可能需要一段时间才能完成。

  3. 反过来引用的可终结对象的任何对象现在都只适用于收集。 / li>

如果您的 .finalize()方法需要很长时间,或者您'创建大量这样的对象时, Finalizer 线程无法跟上需求,对象将继续排队,最终填满整个堆。



还有其他可能的解释,但过度使用 finalize()是一个可能的原因。 有效Java项目7强烈建议终结者


终结器是不可预知的,通常是危险的,而且通常是不必要的。它们的使用会导致不稳定的行为,糟糕的性能和可移植性问题....
$ b


为一个类提供终结器可以在极少数情况下任意拖延回收它的实例。

I'am struggling with unreachable objects in my JVM heap (Java 1.7). As you can see from the picture (all classes on the picture are unreachable), we have more than 74 % objects with no reference, so It should be garbagged collected. This state becomes after 3 weeks uptime on our tomcat 7 server where run only Probe monitoring app, tomcat manager and our webapp which is probably source of the problem.

Our application is based on JSF 1.2 with state saving on client which is what you see in picture below - char arrays with ViewSaveState mostly. When I manually run GC from jVisualVM It removes all unreachable objects and everything is ok until 3 weeks when the heap reaches its limit.

How is it possible that some objects aren't cleaned up?

Our JVM params

-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

STACKTRACES for OutOfMemoryError

I think that cause is hidden somewhere else, stacktraces came from different part of app. There could be some leak, but stacktraces report only last component which claims some memory in time when there isn't any.

    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)

解决方案

One possibility is that you are overloading the JVM with pathological behavior in finalize() methods. If you have classes that override Object.finalize() the JVM has to do a surprising amount of work in order to actually clean them up (and, in turn, clean up all their referenced objects). If you create such objects faster than the garbage collector can process them you'll quickly run into trouble.

This article walks through a pathological finalizer example in detail, but to summarize:

  1. An object with a finalize() method falls out of scope and (conceptually) becomes eligible for GC.
  2. Unlike a normal object which can simply be freed, the JVM holds a special reference to the object via a Finalizer, preventing these objects from being trivially collected. Even short-lived objects survive the initial GC and move into longer-lived sections of the heap if associated with a finalize().
  3. Now these objects will be processed by the dedicated Finalizer thread, which will call .finalize() on each object in turn. Objects that haven't yet had their turn remain on the heap though they're unreachable.
  4. Once the object is processed by the Finalizer thread this last reference is removed and the object can finally actually be GC'ed. Since the object survived one or more collection rounds it may take some time for the GC to get around to it.
  5. Any objects the finalizable object referenced in turn are only now eligible for collection.

If your .finalize() methods take a particularly long time or if you're creating a large number of such objects the Finalizer thread can't keep up with the demand and objects will continue to queue up, eventually filling your entire heap.

There are other possible explanations, but over-use of finalize() is a likely reason. Effective Java Item 7 strongly discourages finalizers:

Finalizers are unpredictable, often dangerous, and generally unnecessary. Their use can cause erratic behavior, poor performance, and portability problems....

Providing a finalizer for a class can, under rare conditions, arbitrarily delay reclamation of its instances.

这篇关于无法访问的对象不是从堆中收集垃圾的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆