无法访问的对象不是从堆中收集垃圾 [英] Unreachable objects are not garbage collected from heap
问题描述
我们的应用程序是基于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)堆空间
jcc.am.ResultSet.getTimestampX(ResultSet.java:1075)
在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)
解决方案一种可能性是您在
finalize()
方法。如果您的类有重载Object.finalize()
的类,那么JVM必须执行令人惊讶的工作量才能真正清理它们(并且依次清理所有他们的引用对象)。如果您创建这些对象的速度比垃圾收集器可以处理它们的速度快,那么您很快就会遇到麻烦。
本文将介绍 pathological finalizer example 详细介绍,但总结如下:
- 具有
finalize()
方法的对象超出范围,并且(概念上)变为符合GC的条件。 一个可以简单释放的普通对象,JVM通过Finalizer
,以防止这些对象被微不足道地收集。即使是短命的对象也能在最初的GC中存活下来,并且如果与finalize()
相关联,则会移入堆中寿命更长的部分。 >现在这些对象将被专用的Finalizer
线程处理,该线程将在每个对象中调用.finalize()
转。尽管它们无法访问,但尚未轮到的对象仍保留在堆上。
- 一旦对象由
Finalizer处理
线程删除最后一个引用,最终实际上可以对该GC进行GC操作。由于对象在一轮或多轮收集后仍然存在,GC可能需要一段时间才能完成。
- 反过来引用的可终结对象的任何对象现在都只适用于收集。 / 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 overrideObject.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:
- An object with a
finalize()
method falls out of scope and (conceptually) becomes eligible for GC.- 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 afinalize()
.- 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.- 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.- 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 theFinalizer
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屋!