Processo de criação de objeto de máquina virtual Java e processo de inicialização

Prefácio

Classifique o processo de criação de objetos e o processo de inicialização

Área de dados de tempo de execução da máquina virtual Java

Processo de criação de objetos

Criação de objeto

  1. Quando a nova instrução é usada, localize a referência de símbolo do parâmetro da instrução no pool constante
  2. Caso contrário, carregue, conecte e inicialize a classe.
  3. A máquina virtual aloca memória para objetos recém-nascidos
  4. Inicialize o espaço de memória alocado para zero, excluindo o cabeçalho do objeto, e inicialize o cabeçalho do objeto (código hash, idade gc, etc.)
  5. Método de objeto de chamada

1. Processo de carregamento de classe

Compreensão profunda da máquina virtual Java Capítulo 7, tempo e processo de carregamento de classe de máquina virtual

2. Layout da memória do objeto

O layout dos objetos na memória é dividido em três áreas: cabeçalho do objeto, dados da instância e preenchimento de alinhamento.

1. Cabeça do objeto

O cabeçalho do objeto da máquina virtual Hotspot inclui principalmente duas partes de dados: Mark Word (campo marcado) e Klass Pointer (tipo de ponteiro). O array terá 1 palavra de largura (32 bits: 4 bytes) para armazenar o comprimento do array .

  • Mark Word é usado para armazenar os dados de tempo de execução do próprio objeto, é a chave para realizar o bloqueio leve e o bloqueio de polarização.
  • Klass Point é o ponteiro do objeto para os metadados de sua classe.A máquina virtual usa esse ponteiro para determinar qual instância de classe o objeto é;

2. Dados de exemplo

Esta parte é a informação efetiva que o objeto realmente armazena e também é o conteúdo de vários tipos de campos definidos no código do programa, incluindo aqueles herdados da classe pai e aqueles definidos na subclasse.

3. Alinhar e preencher

Esta parte não é necessária. Algumas máquinas virtuais requerem que o endereço inicial do objeto seja um múltiplo inteiro de 8 bytes, ou seja, o tamanho do objeto deve ser um múltiplo inteiro de 8 bytes, então o alinhamento é necessário quando for insuficiente.

4. Explicação detalhada de Mark Word

Existem duas maneiras de cabeçalho de objeto na JVM (tome a JVM de 32 bits como exemplo):

// 普通对象
|--------------------------------------------------------------|
|                     Object Header (64 bits)                  |
|------------------------------------|-------------------------|
|        Mark Word (32 bits)         |    Klass Word (32 bits) |
|------------------------------------|-------------------------|

// 数组对象
|---------------------------------------------------------------------------------|
|                                 Object Header (96 bits)                         |
|--------------------------------|-----------------------|------------------------|
|        Mark Word(32bits)       |    Klass Word(32bits) |  array length(32bits)  |
|--------------------------------|-----------------------|------------------------|

  • Esta parte do Mark Word é usada principalmente para armazenar os dados de tempo de execução do próprio objeto, como hashcode, idade de geração do gc, sinalizador de status de bloqueio, bloqueio mantido pelo encadeamento, ID do encadeamento tendencioso, carimbo de data / hora tendencioso, etc.
    O comprimento de bit da palavra de marca é o tamanho de uma palavra da JVM, o que significa que a palavra de marca de uma JVM de 32 bits é de 32 bits e uma JVM de 64 bits é de 64 bits.
    O Mark Word foi projetado como uma estrutura de dados não fixa para armazenar o máximo de dados possível em um espaço de memória muito pequeno. Ele reutiliza seu próprio espaço de armazenamento de acordo com o estado do objeto. Para armazenar mais informações em um tamanho de palavra, JVM will Os dois bits mais baixos da palavra são definidos como bits de marca, e a palavra de marca sob diferentes bits de marca é mostrada como segue:
|-------------------------------------------------------|--------------------|
|                  Mark Word (32 bits)                  |       State        |
|-------------------------------------------------------|--------------------|
| identity_hashcode:25 | age:4 | biased_lock:0 |lock:01 |     Normal无锁      |
|-------------------------------------------------------|--------------------|
|  thread:23 | epoch:2 | age:4 | biased_lock:1| lock:01 |     Biased偏向锁    |
|-------------------------------------------------------|--------------------|
|               ptr_to_lock_record:30         | lock:00 | Lightweight Locked轻量级锁 |
|-------------------------------------------------------|--------------------|
|               ptr_to_heavyweight_monitor:30 | lock:10 | Heavyweight Locked重量级锁 |
|-------------------------------------------------------|--------------------|
|                                             | lock:11 |    Marked for GC   GC标记|
|-------------------------------------------------------|--------------------|

Estado de bloqueio

  • bloqueio: bit de sinalizador de status de bloqueio de 2 bits. Como queremos usar o mínimo possível de bits binários para representar o máximo de informações, o sinalizador de bloqueio está definido. O valor da marca é diferente, o significado de toda a palavra da marca é diferente.
  • bised_lock: se o objeto habilita o sinalizador 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, razão pela qual o valor máximo da opção -XX: MaxTenuringThreshold é 15.
  • Identity_hashcode: código hash de identificação de objeto de 25 bits, usando tecnologia de carregamento lento. Chame o método System.identityHashCode () para calcular e gravar o resultado no cabeçalho do objeto. Quando o objeto estiver bloqueado, o valor será movido para o monitor monitor.
  • thread: O ID do thread que contém 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.

3. Sequência de inicialização do objeto

De acordo com o processo de carregamento da classe, a inicialização da classe clinité executada primeiro e, em seguida, o initmétodo de inicialização do objeto é executado. A sequência é a seguinte:

  1. Variável estática da classe pai Variável
    estática da subclasse

  2. Bloco de código estático da classe pai Bloco de
    código estático da classe filha

  3. Bloco de método de
    classe pai Construtor de classe pai


  4. Construtor de subclasse de bloco de método de subclasse

3. Local de acesso ao objeto

Atualmente, existem duas formas principais de acesso:

  • O identificador
    precisa de uma memória separada do heap como o pool de identificadores, mas a vantagem é que a referência armazena um endereço de identificador estável e apenas o ponteiro de instância no identificador é alterado quando o objeto é movido devido ao GC.
    Lidar com

  • O ponteiro direto tem a
    vantagem de ser rápido
    Acesso direto ao ponteiro

A partir disso, sabemos a que os objetos referenciados na pilha da máquina virtual (tabela de variável local no frame da pilha) se referem nas raízes do GC.

Conclusão

Este artigo analisa o processo geral de criação de objetos, que é de grande ajuda para entender a máquina virtual.

Acho que você gosta

Origin blog.csdn.net/u014099894/article/details/105968386
Recomendado
Clasificación