java - mexico - jmx ejemplo
¿Cómo saber dónde se encuentra exactamente la generación joven/vieja en la memoria? (2)
No sé cómo llegar exactamente a las fronteras de las generaciones jóvenes y viejas (ni siquiera estoy seguro de que sea posible). En el caso de G1 se volvió aún más complicado porque se le permitió tener más de una región de generación anterior debido a la estructura inusual de G1.
Pero puedes usar la heurística complicada para determinar si el objeto está en la generación anterior o no, sin conocer las fronteras de las generaciones.
Usemos algunos conocimientos secretos de magia negra sobre los componentes internos del punto de acceso : cada objeto contiene un encabezado con toda la información necesaria sobre el bloqueo, el código de identificación de identidad y, lo más importante, la edad . La edad de extracción se verá así:
return unsafe.getByte(targetObject, 0L) & 0x78;
donde 0x78 es la máscara correspondiente en el encabezado del objeto para su edad (bits del 4º al 7º inclusive).
Obtenga el parámetro MaxTenuringThreshold
través de la API de administración :
MBeanServer server = ManagementFactory.getPlatformMBeanServer();
HotSpotDiagnosticMXBean bean = ManagementFactory.newPlatformMXBeanProxy(
server,
"com.sun.management:type=HotSpotDiagnostic",
HotSpotDiagnosticMXBean.class);
int threshold = Integer.valueOf(bean.getVMOption("MaxTenuringThreshold").getValue());
Ahora conoces la antigüedad y el umbral de antigüedad de tu aplicación, por lo que puedes asumir que si la edad es mayor que el umbral, está en la generación anterior.
ADVERTENCIA: es heurística basada en la magia y el conocimiento secreto.
- No funcionará, si alguien se sincronizará en el objeto de destino mientras lee su edad, porque VM moverá el encabezado a la pila y reemplazará el encabezado con el puntero para apilar
- No funcionará con
XX:+UseAdaptiveSizePolicy
, por lo que debe deshabilitarlo explícitamente. - Algunos objetos se pueden asignar directamente en la generación anterior (por ejemplo, debido a su tamaño)
- Tipo I propenso a errores
- Este enfoque es ilegal, inseguro y puede ser incorrecto y depende de jvm
Recientemente pude obtener la dirección de un objeto usando la clase sun.misc.Unsafe.
Y ahora estoy tratando de encontrar programáticamente una generación real donde se encuentra mi objeto. Para esto quiero saber los puntos de inicio y final de cada generación. Si Java (Oracle JVM) proporciona alguna herramienta para resolver este problema? Creo que no, ya que incluso diferentes GC requieren diferentes estructuras de memoria (por ejemplo, G1), y esto hace que la tarea sea aún más interesante :)
Lo que quiero saber aquí es solo un par de números que representan los límites de las generaciones en la memoria, así:
young gen: start point - 8501702198
end point - 9601256348
Me encantaría escuchar incluso sus ideas más locas sobre una magia negra que permite determinar dónde se colocan las diferentes áreas de generación en la memoria.
Esto es posible con HotSpot JVM aunque de alguna manera complicado.
La idea clave es usar VMStructs
: la información sobre las constantes internas de HotSpot y los tipos incorporados directamente en la biblioteca compartida de JVM.
Por ejemplo, la variable global ParallelScavengeHeap::_young_gen
VM contiene el puntero a la estructura PSYoungGen
que tiene el miembro _virtual_space
con los límites de la generación joven de colectores paralelos. De forma similar, GenCollectedHeap::_gch
global apunta a la estructura que describe las generaciones de recopiladores de CMS.
Hice un proyecto de prueba de concepto para demostrar el uso de VMStructs. Es puro Java, no se requieren bibliotecas adicionales, pero se basa profundamente en las partes internas de JDK no documentadas y puede no funcionar en todas las versiones de Java. He probado esto en JDK 8u40 y JDK 7u80 en Windows y Linux.
- JVM.java - el código para leer VMStructs;
- HeapInfo.java - el programa de ejemplo para obtener direcciones de generaciones Heap.