Por que aprender cabeçalhos de objeto Java
Aprender o cabeçalho do objeto Java é principalmente para compreender os princípios subjacentes da sincronização, o processo de atualização de bloqueio sincronizado e programação Java simultânea.
Cabeçalho do objeto JAVA
Devido à ideia orientada a objetos do Java, um grande número de objetos de armazenamento são necessários na JVM. A fim de realizar algumas funções adicionais durante o armazenamento, alguns campos de marca precisam ser adicionados aos objetos para aprimorar as funções do objeto. Esses campos de marca constituem o cabeçalho do objeto.
Na máquina virtual HotSpot, o layout dos objetos armazenados na memória pode ser dividido em três áreas: cabeçalho do objeto (Cabeçalho), dados da instância (Dados da Instância) e preenchimento do alinhamento (Padding).
Ou seja, objeto JAVA = cabeçalho do objeto + dados da instância + preenchimento do objeto.
Dentre eles, o cabeçalho do objeto é composto por duas partes, uma parte é usada para armazenar seus próprios dados de tempo de execução, denominados Mark Word, e a outra parte é o ponteiro de tipo, e o objeto aponta para o ponteiro de metadados da classe.
Cabeçalho do objeto = Mark Word + tipo de ponteiro
(quando a compressão do ponteiro não está ativada)
Em um sistema de 32 bits, Mark Word = 4 bytes = 32 bits e cabeçalho do objeto = 8 bytes = 64 bits;
em um sistema de 64 bits, Mark Word = 8 bytes = 64 bits, cabeçalho do objeto = 16 bytes = 128 bits;
bytes são bytes e bits são bits. Portanto, no sistema de máquina virtual JVM de 32 bits, a parte Mark Word ocupa 4 bytes e a parte Klass Word também ocupa 4 bytes, portanto, o tamanho do cabeçalho do objeto é de 8 bytes. No sistema de máquina virtual JVM de 64 bits, a parte Mark Word ocupa 8 bytes e a parte Klass Word também ocupa 8 bytes, então o tamanho do cabeçalho do objeto é 16 bytes.
Cabeçalho de objeto de máquina virtual de 32 bits
Cabeçalho de objeto de objeto comum de máquina virtual de 32 bits
|-----------------------------------------------------------|
| Object Header (64 bits) |
|---------------------------------|-------------------------|
| Mark Word (32 bits) | Klass Word (32 bits) |
|---------------------------------|-------------------------|
Cabeçalho de objeto de objeto de array de máquina virtual de 32 bits
|---------------------------------------------------------------------------------|
| Object Header (96 bits) |
|--------------------------------|-----------------------|------------------------|
| Mark Word(32bits) | Klass Word(32bits) | array length(32bits) |
|--------------------------------|-----------------------|------------------------|
Os detalhes do cabeçalho do objeto de máquina virtual de 32 bits são os seguintes
|-----------------------------------------------------------------------------------------------------------------|
| Object Header(64bits) |
|-----------------------------------------------------------------------------------------------------------------|
| Mark Word(32bits) | Klass Word(32bits) | State |
|-----------------------------------------------------------------------------------------------------------------|
| hashcode:25 | age:4 | biased_lock:0 | 01 | OOP to metadata object | Nomal |
|-----------------------------------------------------------------------------------------------------------------|
| thread:23 | epoch:2 | age:4 | biased_lock:1 | 01 | OOP to metadata object | Biased |
|-----------------------------------------------------------------------------------------------------------------|
| ptr_to_lock_record:30 | 00 | OOP to metadata object | Lightweight Locked |
|-----------------------------------------------------------------------------------------------------------------|
| ptr_to_heavyweight_monitor:30 | 10 | OOP to metadata object | Heavyweight Locked |
|-----------------------------------------------------------------------------------------------------------------|
| | 11 | OOP to metadata object | Marked for GC |
|-----------------------------------------------------------------------------------------------------------------|
Cabeçalho de objeto de máquina virtual de 64 bits
|-----------------------------------------------------------------------------------------------------------------|
| Object Header(128bits) |
|-----------------------------------------------------------------------------------------------------------------|
| Mark Word(64bits) | Klass Word(64bits) | State |
|-----------------------------------------------------------------------------------------------------------------|
| unused:25|identity_hashcode:31|unused:1|age:4|biase_lock:0| 01 | OOP to metadata object | Nomal |
|-----------------------------------------------------------------------------------------------------------------|
| thread:54| epoch:2 |unused:1|age:4|biase_lock:1| 01 | OOP to metadata object | Biased |
|-----------------------------------------------------------------------------------------------------------------|
| ptr_to_lock_record:62 | 00 | OOP to metadata object | Lightweight Locked |
|-----------------------------------------------------------------------------------------------------------------|
| ptr_to_heavyweight_monitor:62 | 10 | OOP to metadata object | Heavyweight Locked |
|-----------------------------------------------------------------------------------------------------------------|
| | 11 | OOP to metadata object | Marked for GC |
|-----------------------------------------------------------------------------------------------------------------|
lock : bit de sinalizador de status de bloqueio de 2 bits. Como queremos usar o mínimo de bits binários possível para representar o máximo de informações possível, o sinalizador de bloqueio é definido. O valor da marca é diferente, o significado de toda a palavra da marca é diferente.
enviesamento | fechadura | status |
---|---|---|
0 | 01 | não feche |
1 | 01 | Bloqueio de polarização |
0 | 00 | Fechadura leve |
0 | 10 | Trava de peso pesado |
0 | 11 | Marca GC |
bised_lock : se o objeto habilita o flag de bloqueio polarizado, que ocupa apenas 1 bit binário. Quando for 1, significa que o objeto possui um bloqueio polarizado; quando for 0, significa que o objeto não possui um bloqueio polarizado.
idade : idade do objeto Java de 4 dígitos. No GC, se o objeto for copiado uma vez na área do sobrevivente, a idade aumenta em 1. Quando o assunto atinge o limite definido, ele será promovido à velhice. Por padrão, o limite de idade para GC paralelo é 15 e o limite de idade para GC simultâneo é 6. Como a idade tem apenas 4 bits, o valor máximo é 15, por isso o -XX:MaxTenuringThreshold
valor máximo da opção é 15.
Identity_hashcode : código hash de identificação de objeto de 25 bits, usando tecnologia de carregamento lento. Chame o método de System.identityHashCode()
cálculo e escreva o resultado no cabeçalho do objeto. Quando o objeto estiver bloqueado, o valor será movido para o monitor monitor.
thread : ID do thread segurando o bloqueio de polarização.
epoch : bias timestamp.
ptr_to_lock_record : Ponteiro para o registro de bloqueio na pilha.
ptr_to_heavyweight_monitor : Ponteiro para monitorar o monitor.
Como visualizar o cabeçalho do objeto
Para visualizar o cabeçalho do objeto, você precisa usar a ferramenta JOL.
<dependency>
<groupId>org.openjdk.jol</groupId>
<artifactId>jol-core</artifactId>
<version>0.10</version>
</dependency>
import org.openjdk.jol.info.ClassLayout;
import org.openjdk.jol.vm.VM;
import static java.lang.System.out;
public class TestBiased {
public static void main(String[] args) {
Dog d= new Dog();
//打印JVM的详细信息
out.println(VM.current().details());
//打印对应的对象头信息
out.println(ClassLayout.parseInstance(a).toPrintable());
}
}
class Dog {
}
A impressão é aproximadamente a seguinte.
21:46:08.204 c.TestBiased [main] - # Running 64-bit HotSpot VM.
# Objects are 8 bytes aligned.
# Field sizes by type: 8, 1, 1, 2, 2, 4, 4, 8, 8 [bytes]
# Array element sizes: 8, 1, 1, 2, 2, 4, 4, 8, 8 [bytes]
21:46:08.215 TestBiased [main] - cn.itcast.test.Dog object internals:
OFFSET SIZE TYPE DESCRIPTION VALUE
0 4 (object header) 01 00 00 00 (00000001 00000000 00000000 00000000) (1)
4 4 (object header) 00 00 00 00 (00000000 00000000 00000000 00000000) (0)
8 4 (object header) 50 c8 e1 3f (01010000 11001000 11100001 00111111) (1071761488)
12 4 (object header) 71 01 00 00 (01110001 00000001 00000000 00000000) (369)
Instance size: 16 bytes
Space losses: 0 bytes internal + 0 bytes external = 0 bytes total
Se a impressão for diferente, você pode adicionar o parâmetro de opções VM -XX:-UseCompressedOops
para desativar a compactação do ponteiro.
Para entender o número de VALUE, você precisa entender o armazenamento de pouco endian
referência
memória-eficiente-java
compreensão aprofundada do cabeçalho do objeto Java marca palavra
Java objeto cabeçalho explicação detalhada da
entrevista de recrutamento da escola
Java estrutura do objeto Java e princípio de implementação de bloqueio e explicação detalhada MarkWord para
matar o entrevistador 1-sincronizado princípio subjacente (do cabeçalho do objeto Java à otimização de compilação instantânea)
Explore o armazenamento header-big-endian do objeto Java e o armazenamento little-endian