¿Alguna vez te has preguntado cómo se ven los objetos java desde adentro?
Debajo del gato habrá una descripción detallada del encabezado del objeto java, en qué consiste y cuánta memoria necesita.
Para empezar, recuerde que en jvm cualquier objeto en la memoria consiste en el encabezado del objeto y las variables del objeto (enlaces y primitivas). Además, el tamaño final del objeto puede expandirse para convertirse en un múltiplo de 8 bytes.
El título de cada objeto (excepto la matriz) consta de dos palabras de máquina: palabra de marca y palabra de clase . Las matrices tienen 32 bits adicionales para describir la longitud de la matriz.
La palabra marca almacena el código hash de identidad, los bits utilizados por el recolector de basura y los bits utilizados para las cerraduras. Siempre puede encontrar más detalles en los correspondientes tipos de OpenJDK markOop.hpp .
Una palabra de clase almacena un puntero a la clase misma, es decir, al lugar donde se encuentra la información sobre este tipo de datos: métodos, anotaciones, herencia y más. También se pueden encontrar más detalles en los correspondientes tipos de OpenJDK de klass.hpp .
Echemos un vistazo más de cerca al título del objeto y , en particular , a la palabra marca.
32 bits jvm

Como puede ver en la tabla, el contenido de la palabra Mark puede variar mucho según el estado actual del objeto.
Estado normal del objeto (biased_lock = 0, lock = 01)
- identity_hashcode es el hash de un objeto que aparece perezosamente. Si el objeto tiene una llamada System.identityHashCode (obj) por primera vez, este hash se calculará y se escribirá en el encabezado del objeto.
En otros estados, cuando varias secuencias compiten por un objeto, identity_hashcode se almacenará no en el encabezado del objeto, sino en el monitor del objeto. - edad: la cantidad de recolecciones de basura experimentadas. Cuando la edad alcanza el número máximo de umbral de tenencia,
el objeto se mueve al área de la cadera de la vieja generación. - biased_lock: contiene 1 si el bloqueo sesgado está habilitado para este objeto; de lo contrario, 0.
Un poco masCuando Biased Locking está activado, el objeto se mueve como si fuera el primer objeto que capturó su monitor. La captura posterior del objeto en la misma secuencia será un poco más rápida.
Aquí están los prerrequisitos teóricos básicos para este bloqueo:
- A lo largo de la vida del objeto, es predominantemente propiedad de uno
- Si el hilo recientemente usó un bloqueo en este objeto, lo más probable es que la memoria caché del procesador aún contenga los datos que se necesitarán para volver a capturar este objeto.
El bloqueo sesgado está habilitado de forma predeterminada desde java 6, -XX: -UseBiasedLocking
- bloqueo: contiene el código de estado de bloqueo. 00 - Peso ligero bloqueado, 01 - Desbloqueado o sesgado, 10 - Peso pesado bloqueado, 11 - Marcado para recolección de basura.
Es decir, en la tabla, el estado de un objeto está determinado por la combinación de los bits biased_lock y lock.
Modo bloqueado sesgado (biased_lock = 1, lock = 01)
- subproceso: en el modo de bloqueo sesgado se supone que el objeto pertenece predominantemente a un subproceso particular, la identificación de este subproceso se almacena en el campo.
- epoch contiene algún indicador temporal de propiedad del objeto por un hilo cuya identificación se almacena en el hilo
Modo bloqueado ligero (bloqueo = 00)
En este modo, se supone que el tiempo de captura de este objeto por diferentes flujos no se cruza en absoluto o no se solapa de manera insignificante. En este modo, en lugar de bloquear el sistema operativo, la JVM usa atómicos.
- ptr_to_lock_record - CAS (comparar y establecer) dentro del ciclo de giro se usa para establecer / esperar un bloqueo.
Como referencia, el tiempo mínimo de bloqueo del sistema operativo estará en la región de aproximadamente 10 ms, con la ayuda de los átomos, la corriente no se duerme, pero continúa trillando un ciclo pequeño, y tan pronto como el recurso esté libre, el ciclo atómico terminará y la corriente capturará inmediatamente este objeto.
Modo bloqueado de peso pesado (bloqueo = 10)
- ptr_to_heavyweight_monitor: si el tiempo de captura de este objeto con diferentes flujos se superpondrá significativamente, entonces el bloqueo ligero se reemplazará por un bloqueo pesado. Se escribirá un puntero al monitor en ptr_to_heavyweight_monitor. Se utiliza el bloqueo del sistema operativo.
Entonces, en jvm de 32 bits, el encabezado del objeto consta de 8 bytes. Las matrices tienen además 4 bytes.
Jvm de 64 bits

En una jvm de 64 bits, el encabezado del objeto consta de 16 bytes. Las matrices tienen además 4 bytes.
Jvm de 64 bits con compresión de puntero

Un encabezado de objeto consta de 12 bytes. Las matrices tienen además 4 bytes.
Un poco sobre la compresión del puntero. Para un puntero de 32 bits, el espacio de direcciones está limitado a 4 GB. Sin embargo, si recordamos nuevamente que en jvm el tamaño de un objeto es un múltiplo de 8 bytes, entonces podemos usar un pseudo puntero de 35 bits, con tres ceros al final. Y, por lo tanto, ya se refieren a 32 GB de memoria. La compresión no es gratuita, el precio es una operación adicional (puntero << 3) para cualquier llamada al montón.
Enlace al artículo original:
Encabezado de objeto Java
También me gustaría agregar que todo lo que se describe aquí no es un dogma, quizás en otras versiones de jvm el título del objeto será diferente. Descrito aquí es relevante para openjdk 8.