rios rio mundo mas los india imagenes dibujo contaminados contaminado citarum java tomcat garbage-collection jvm heap

java - rio - Los objetos inalcanzables no son basura recolectada del montón



rio contaminado dibujo (3)

Hay varios aspectos en el comportamiento que enfrenta. En primer lugar, tener objetos inalcanzables dentro del montón en cualquier momento dado es perfectamente normal. Garbage Collection limpiará los objetos inalcanzables durante la próxima ejecución y limpiará el montón de ellos. Por lo tanto, ver estructuras de datos inalcanzables en el volcado del heap no es malo ni anormal.

Pero al enfrentar java.lang.OutOfMemoryError: error de espacio en el montón de Java, estas referencias inalcanzables deberían haberse limpiado. Puede verificar esto agregando -XX: + HeapDumpOnOutOfMemoryError a sus parámetros de inicio, desencadenando el volcado del montón en el próximo OutOfMemoryError generado. Cuando ahora rastreas este volcado, no deberías ver los objetos inalcanzables, al menos no de un tamaño significativo.

Después de entender esto, el problema subyacente aún no está claro, una de las posibles causas definitivamente puede ser una pérdida de montón. Para esto, puede intentar continuar con el mismo volcado de memoria obtenido durante el bloqueo de JVM con OutOfMemoryError, o puede hacer su vida más fácil y conectar un detector de fuga de memoria de Java para encontrar la ubicación exacta de la fuga en su código fuente.

Estoy luchando con objetos inalcanzables en mi montón de JVM (Java 1.7). Como se puede ver en la imagen (no se puede acceder a todas las clases de la imagen), tenemos más del 74% de objetos sin referencia, por lo que debe recogerse con garbagged. Este estado se convierte luego de 3 semanas de actividad en nuestro servidor tomcat 7 donde solo se ejecuta la aplicación de monitoreo Probe, el administrador de tomcat y nuestra aplicación web, que probablemente sea la fuente del problema.

Nuestra aplicación se basa en JSF 1.2 con ahorro de estado en el cliente, que es lo que se ve en la imagen a continuación: matrices de caracteres con ViewSaveState principalmente. Cuando ejecuto manualmente GC desde jVisualVM, elimina todos los objetos inalcanzables y todo está bien hasta 3 semanas cuando el montón llega a su límite.

¿Cómo es posible que algunos objetos no se limpien?

Nuestros param de 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

STACKTRACES para OutOfMemoryError

Creo que la causa está oculta en otro lado, stacktraces proviene de diferentes partes de la aplicación. Puede haber alguna fuga, pero stacktraces informa solo el último componente que reclama memoria en el tiempo cuando no hay ninguna.

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)


Una posibilidad es que esté sobrecargando la JVM con un comportamiento patológico en los métodos de finalize() . Si tiene clases que anulan Object.finalize() la JVM tiene que hacer una cantidad sorprendente de trabajo para realmente limpiarlas (y, a su vez, limpiar todos los objetos a los que hace referencia). Si crea dichos objetos más rápido de lo que el recolector de basura puede procesarlos, rápidamente tendrá problemas.

Este artículo repasa un ejemplo de finalizador patológico en detalle, pero para resumir:

  1. Un objeto con un método finalize() cae fuera del alcance y (conceptualmente) se vuelve elegible para GC.
  2. A diferencia de un objeto normal que simplemente puede liberarse, la JVM mantiene una referencia especial al objeto a través de un Finalizer , lo que evita que estos objetos se recolecten trivialmente. Incluso los objetos de corta vida sobreviven al GC inicial y se mueven a secciones de mayor duración del montón si están asociados con un finalize() .
  3. Ahora estos objetos serán procesados ​​por el hilo de Finalizer dedicado, que llamará a .finalize() en cada objeto sucesivamente. Los objetos que aún no han tenido su turno permanecen en el montón a pesar de que son inalcanzables.
  4. Una vez que el objeto es procesado por el hilo del Finalizer esta última referencia se elimina y el objeto finalmente puede ser GC. Debido a que el objeto sobrevivió a una o más rondas de recolección, el GC puede demorar un tiempo para lograrlo.
  5. Todos los objetos a los que se hace referencia en el objeto finalizable solo son ahora elegibles para la recopilación.

Si sus métodos .finalize() tardan un tiempo particularmente largo o si está creando una gran cantidad de tales objetos, el hilo del Finalizer no puede satisfacer la demanda y los objetos continuarán haciendo cola, llenando finalmente todo su montón.

Hay otras explicaciones posibles, pero el uso excesivo de finalize() es una razón probable. El efectivo artículo 7 de Java desaconseja a los finalizadores :

Los finalizadores son impredecibles, a menudo peligrosos y generalmente innecesarios. Su uso puede causar un comportamiento errático, bajo rendimiento y problemas de portabilidad ....

Proporcionar un finalizador para una clase puede, en raras condiciones, retrasar arbitrariamente la recuperación de sus instancias.


Esta pregunta podría estar relacionada con esta

Un montón de Java abrumado por objetos inalcanzables

Lo encontré ya que estoy enfrentando el mismo problema en un IBM JVM 5 runninf en AIX 6.1

La única cantidad de almacenamiento retenido que crece consistentemente entre dos fullgcs son los objetos inalcanzables, marcados, si no estoy equivocado, con ROOT como el dominador en Eclipse MAT.

Para obtener estos volcados, configuro la JVM para crear un sysdump después de un fullgc usando la opción Xdump (solo para las JVM de IBM, creo)

Espero que esto ayude, y si alguien sabe si el registro detallado de GC deja un rastro de los objetos inalcanzables que no se pudieron limpiar, ¡por favor hágamelo saber!

Carlos