Acredita -se geralmente que os objetos novos sejam alocados na pilha, mas isso não está completamente correto. Através da análise do processo de alocação de objetos Java, descobrimos que, além de ser alocado na pilha, os objetos também podem alocar espaço na pilha ou no TLAB. A base técnica para alocar objetos na pilha é a análise de escape e a substituição escalar. Este artigo apresenta principalmente a análise de fuga.
Definição de análise de fuga
A análise de escape é um algoritmo multifuncional de análise global de fluxo de dados que pode efetivamente reduzir a pressão de alocação de carga síncrona e de alocação de memória nos programas Java.
Através da análise de escape, o compilador de hotspot Java pode analisar o escopo do uso da referência de um novo objeto e determinar se alocar o objeto à pilha.
O Java suporta e permite opções de análise de escape no Java SE 6U23 e versões posteriores. O Hotspot JIT Compiler da Java pode executar a análise de escape do código quando o método é sobrecarregado ou carregado dinamicamente.
O comportamento básico da análise de fuga é analisar o escopo dinâmico de um objeto: quando um objeto é definido em um método, ele pode ser referenciado por um método externo.
Método Escape: por exemplo, passe como um parâmetro de chamada para outros métodos.
Escape de threads: pode ser acessado por encadeamentos externos, como atribuir valores a variáveis de classe ou variáveis de instância que podem ser acessadas em outros threads.
Base teórica da análise de fuga
A análise de escape é realizada com base no algoritmo descrito por Jong-deok Choi, Manish Gupta, Mauricio Seffano, Vugnamam C. Sreedhar, Sam Midkiff e outros no artigo "Análise de escape para Java".
Esse algoritmo apresenta um gráfico conectado e usa o gráfico conectado para construir a relação acessível entre o objeto e a referência do objeto e, com base nisso, é proposto um método combinado de análise de fluxo de dados. Como o algoritmo é dependente do contexto e sensível ao fluxo, e simula as relações aninhadas em qualquer nível do objeto, a precisão da análise é alta, mas o tempo de execução e o consumo de memória são relativamente grandes.
A maioria das implementações da análise de fuga é baseada na premissa do "mundo fechado": todos os métodos possíveis executados são conhecidos antes da análise de fuga, e a operação real do programa não alterará o relacionamento de chamada entre eles. Mas quando um programa Java real é executado, essas suposições não são verdadeiras. Muitos recursos dos programas Java, como carregamento dinâmico de classe, chamando funções locais e refletindo chamadas de programa, quebrarão a chamada convenção "World Fecht World".
Operações de processamento após análise de fuga
Após a análise de fuga, três possíveis estados de fuga do objeto podem ser obtidos:
Globalescape: isto é, a referência de um objeto escapa de um método ou encadeamento. Por exemplo, a referência de um objeto é copiada para uma variável de classe ou armazenada em um objeto que escapou, ou a referência do objeto é retornada ao método de chamada como o valor de retorno do método.
Argescape (escape de nível de parâmetro): isto é, a aplicação do objeto passada para um método durante o processo de chamada do método. Esse estado pode ser determinado analisando o código binário do método que está sendo ajustado.
Noescape: um objeto que pode ser substituído por escalares. O objeto não pode ser alocado em uma pilha tradicional.
O compilador pode usar os resultados da análise de fuga para otimizar o programa:
O objeto de alocação de heap se torna um objeto de alocação de pilha: um objeto em um método e a referência do objeto não escapa, portanto esse método pode ser alocado na memória da pilha e é muito comum para empilhar a memória.
Elimine a sincronização: o custo da sincronização do encadeamento é bastante alto e as consequências da sincronização são reduzidas de simultaneidade e desempenho. A análise de escape pode determinar se um objeto é sempre acessado por apenas um thread. Se for acessado por apenas um thread, a operação de sincronização do objeto poderá ser convertida em uma operação sem proteção de sincronização, o que pode melhorar bastante o grau de concorrência e desempenho.
Substituição vetorial: Método de análise de escape Se você achar que a estrutura de armazenamento de memória do objeto não precisa ser realizada continuamente, você pode salvar peças e até todo o objeto nos registros da CPU, o que pode melhorar bastante a velocidade de acesso.