1. Modelo de memória java
Ao executar um programa, a máquina virtual Java divide a memória que ele consegue em várias áreas de dados. A distribuição dessas áreas de dados é mostrada na figura abaixo:
Contador do programa: Uma pequena área de memória apontando para o bytecode atualmente executado. Se o thread estiver executando um método Java, esse contador registra o endereço da instrução ByteCode da máquina virtual que está sendo executada. Se o método nativo for executado, o valor da calculadora estará vazio.
Pilha de máquina virtual java: os threads são privados e seu ciclo de vida é consistente com os threads. Quando cada método é executado, um quadro de pilha será criado para armazenar informações como tabelas de variáveis locais, pilhas de operando, links dinâmicos, saídas de método etc.
Pilha de métodos locais: as funções são semelhantes à pilha de máquinas virtuais, exceto que a pilha de máquina virtual executa serviços de método Java para a máquina virtual, enquanto a pilha de métodos local serve o método nativo usado.
Java Heap: É a maior peça de memória de gerenciamento de máquina virtual, compartilhada por todos os threads, essa área é usada para armazenar instâncias de objetos e quase todos os objetos são alocados nesta área. A pilha Java é a principal área de reciclagem de memória. Do ponto de vista da reciclagem de memória, como a maioria dos colecionadores atuais usa algoritmos de coleta geracional, a pilha Java também pode ser subdividida em: a nova geração e a geração antiga. Se for subdividido um pouco, poderá ser dividido no espaço do Éden, do espaço de sobrevivência, ao espaço de sobrevivência etc. De acordo com a especificação da máquina virtual Java, o heap java pode estar em um espaço fisicamente descontínuo, desde que seja logicamente contínuo.
Área do método: como o Java, é compartilhado por vários threads e é usado para armazenar dados como informações de classe que foram carregadas pela máquina virtual, sempre ligadas, variáveis estáticas, código compilado pelo compilador instantâneo.
Pool constante de tempo de execução, o pool constante de tempo de execução faz parte da área do método. Além da versão de classe, campos, métodos, interfaces e outras informações de descrição, também há um pool constante no arquivo de classe, que é usado para armazenar várias referências literal e simbólico geradas durante o período de compilação. Durante o tempo de execução, novas constantes podem ser colocadas na piscina constante. O mais comumente usado é o método intern () da classe String. Quando uma instância de string chama de estagiário, Java descobre se existem as mesmas constantes de sequência unicode no pool constante. Se houver, ele retorna sua referência; Caso contrário, adicione um unicode igual à string de instância e retorna sua referência.
2. Como determinar o objeto de lixo
Existem várias instâncias de objetos armazenadas na pilha Java. Antes do coletor de lixo recicla a pilha, ele primeiro precisa determinar quais objetos ainda estão "vivos" e quais "mortos", ou seja, objetos que não serão usados por nenhum meio.
Contagem de citações
O método de contagem de citação é simples de implementar e eficientemente e é um bom algoritmo na maioria dos casos. O princípio é: adicione um contador de referência ao objeto. Sempre que existe um local para fazer referência ao objeto, o contador é aumentado em 1. Quando a referência falha, o contador é reduzido em 1. Quando o valor do contador é 0, significa que o objeto não é mais usado. Deve -se notar que o método de contagem de referência é difícil de resolver o problema de referência mútua entre objetos e as máquinas virtuais Java mainstream não usam o método de contagem de referência para gerenciar a memória.
Algoritmo de análise de acessibilidade
A idéia básica desse algoritmo é pesquisar para baixo através de uma série de objetos chamados "GC Roots" como ponto de partida, começando desses nós. O caminho pesquisado é chamado de cadeia de referência. Quando um objeto não está conectado às raízes GC sem nenhuma cadeia de referência (nas palavras da teoria dos gráficos, é de raízes GC para esse objeto que é inacessível), está provado que esse objeto não está disponível. Conforme mostrado na figura, embora os objetos 5, o objeto 6 e o objeto 7 estejam relacionados entre si, eles são inacessíveis às raízes GC, para que sejam julgados como objetos recicláveis.
Na linguagem Java, os seguintes objetos que podem ser usados como raízes GC incluem:
Objeto referenciado na pilha da máquina virtual (tabela de variável local no quadro da pilha).
Objeto referenciado pelo atributo estático da classe na área do método.
Objeto referenciado por constantes na área do método.
Objetos mencionados pelo JNI (ou seja, o método nativo geral) na pilha de métodos locais.
Agora, a questão é: o algoritmo de análise de acessibilidade terá um problema de referência circular entre objetos? A resposta é sim, ou seja, não haverá problema de referência circular entre objetos. O GC Root é um "ponto de partida" especialmente definido fora do gráfico do objeto e não pode ser referenciado por objetos no gráfico do objeto.
Morrer ou não morrer
Mesmo objetos inacessíveis no algoritmo de análise de acessibilidade não são "deve morrer". Neste momento, eles estão temporariamente no estágio de "liberdade condicional". Para declarar verdadeiramente um objeto morto, ele deve passar por pelo menos dois processos de marcação: se o objeto descobrir que não há cadeia de referência conectada às raízes do GC após a realização da análise de acessibilidade, ele será marcado pela primeira vez e filtrado. A condição de filtragem é se é necessário para esse objeto executar o método FINAPZE (). Quando o objeto não substitui o método FINAPZE (), ou o método FINAPZE () foi chamado pela máquina virtual, a máquina virtual considera os dois casos como "sem necessidade de executar". No programa, você pode substituir o FINAPZE () para criar um processo de auto-alvação "emocionante", mas essa é apenas uma chance.
/** * Este código demonstra dois pontos: * 1. Os objetos podem se salvar quando são GC. * 2. Existe apenas uma chance de auto-resgate, porque o método finapze () de um objeto só será chamado automaticamente uma vez pelo sistema na maioria * @author zzm */ pubpc class finapzeescapeGC {pubPC estático finapzeescapegc save_hook = null; pubpc void isapve () {System.out.println ("Sim, ainda estou apve: :)"); } @Override Protected void finapze () lança lançável {super.finapze (); System.out.println ("Finapze mehtod executado!"); Finapzeescapegc.save_hook = this; } pubpc estático void main (string [] args) lança arremesso {save_hook = new FINAPZEESCAPEGC (); // O objeto se salva com sucesso pela primeira vez save_hook = null; System.gc (); // porque o método FINAPZE tem baixa prioridade, pausa por 0,5 segundos para aguardar o thread.Sleep (500); if (save_hook! = null) {save_hook.isapve (); } else {System.out.println ("Não, estou morto :(");} // O código a seguir é exatamente o mesmo que o acima, mas desta vez o auto-resgate falhou. Save_hook = null; system.gc (); // porque o método finapze tem uma baixa prioridade, ele faz pausas para 0,5 segundos para aguardar para ele. Save_hook.isapve ();O resultado em execução é:
Finapze Mehtod executado! Sim, ainda estou apvela :) Não, estou morto :(
Vamos falar sobre citações
Seja julgando o número de referências de um objeto por meio de um algoritmo de contagem de referência ou determinando se a cadeia de referência do objeto é acessível por meio de um algoritmo de análise de acessibilidade, determinando se a sobrevivência do objeto está relacionada à "referência". Antes do JDK 1.2, a definição de referências em Java era muito tradicional: se o valor armazenado nos dados do tipo de referência representa o endereço inicial de outra peça de memória, diz -se que esta peça de memória representa uma referência. Após o JDK 1.2, Java expandiu o conceito de referência e dividiu referências em quatro tipos: forte referência, referência suave, referência fraca e referência fantasma. A força desses quatro tipos de referência gradualmente enfraqueceu por sua vez.
• Citação forte refere -se a referências comuns no código do programa, como "objeto obj = new objeto ()". Enquanto a citação forte ainda existir, o coletor de lixo nunca reciclará o objeto referenciado.
• Referências suaves são usadas para descrever alguns objetos úteis, mas não necessários. Para objetos associados à referência suave, esses objetos serão listados no escopo da reciclagem para uma segunda reciclagem antes que o sistema esteja prestes a ter uma exceção de transbordamento de memória. Se não houver memória suficiente para esta reciclagem, uma exceção de transbordamento de memória será lançada. Após o JDK 1.2, a classe Softreference é fornecida para implementar referências suaves.
• Referências fracas também são usadas para descrever objetos não essenciais, mas sua força é mais fraca que as referências suaves. Objetos associados a referências fracas só podem sobreviver até que a próxima coleta de lixo ocorra. Quando o coletor de lixo funciona, objetos que estão associados apenas a referências fracas são coletadas, independentemente de a memória atual ser suficiente. Após o JDK 1.2, a classe de referência fraca é fornecida para implementar referências fracas.
• As citações de vazios também são chamadas de citações fantasmas ou citações fantasmas, e elas são o relacionamento de citação mais fraco. Se um objeto tem uma referência virtual não terá nenhum impacto em seu tempo de sobrevivência, nem será possível obter uma instância de objeto por meio de referência virtual. O único objetivo de configurar associações de referência virtual para um objeto é receber uma notificação do sistema quando o objeto é reciclado pelo coletor. Após o JDK 1.2, a classe Phantomreference é fornecida para implementar referências virtuais.
Exemplo de uso de referência suave:
pacote jvm; importar java.lang.ref.softreference; classe nó {pubpc string msg = "";} classe pubpc hello {pubpc static void main (string [] args) {node node1 = new node (); // forte referência node1.msg = "node1"; softreference <Node> node2 = new softreference <Node> (node1); // Soft Reference Node2.get (). Msg = "node2"; System.out.println (node1.msg); System.out.println (node2.get (). Msg);}}O resultado da saída é:
node2Node2
3. Algoritmo típico de coleta de lixo
1. Algoritmo de Weep-Weep (Mark-Clear)
Este é o algoritmo de coleta de lixo mais básico. A razão pela qual se diz ser a mais básica é que é a mais fácil de implementar e a idéia mais simples. O algoritmo de limpeza de marcas é dividido em dois estágios: o estágio de marcação e o estágio de limpeza. A tarefa do estágio de marcação é marcar todos os objetos que precisam ser reciclados, e o estágio de limpeza é reciclar o espaço ocupado pelos objetos marcados. O processo específico é mostrado na figura abaixo:
Pode ser facilmente visto a partir da figura que o algoritmo de limpeza de marcas é mais fácil de implementar, mas há um problema sério que é fácil gerar fragmentos de memória. Muitos fragmentos podem causar incapacidade de encontrar espaço suficiente ao alocar espaço para objetos grandes no processo subsequente e desencadear uma nova ação de coleta de lixo com antecedência.
2. Cópia do algoritmo
Para resolver as deficiências do algoritmo de varredura de marcas, o algoritmo de cópia foi proposto. Ele divide a memória disponível em dois pedaços de tamanho igual por capacidade, usando apenas uma peça de cada vez. Quando este pedaço de memória for usado, copie o objeto ainda viva para outra peça e limpe o espaço de memória usado de uma só vez, para que os problemas de fragmentação da memória não ocorram. O processo específico é mostrado na figura abaixo:
Embora esse algoritmo seja simples de implementar, eficiente para executar e não é fácil de gerar fragmentação de memória, é caro usar o espaço de memória porque a memória que pode ser usada é reduzida a metade da original.
Obviamente, a eficiência do algoritmo de cópia tem muito a ver com o número de objetos sobreviventes. Se houver muitos objetos sobreviventes, a eficiência do algoritmo de cópia será bastante reduzida.
3. Algoritmo de compacto de marcação (colação de marcas)
Para resolver as deficiências do algoritmo de cópia e fazer pleno uso do espaço de memória, o algoritmo de compacto de marcas é proposto. O algoritmo marca o mesmo que o mark-sweep, mas depois de concluir a marca, ele não limpa diretamente os objetos recicláveis, mas move todos os objetos vivos para uma extremidade e depois limpa a memória fora do limite final. O processo específico é mostrado na figura abaixo:
4. Algoritmo de coleta geracional
Atualmente, o algoritmo de coleta de geração é usado pela maioria dos coletores de lixo da JVM. Sua idéia principal é dividir a memória em várias regiões diferentes, de acordo com o ciclo de vida da sobrevivência do objeto. De um modo geral, a área da pilha é dividida na antiga geração e na geração jovem. A característica da geração antiga é que apenas um pequeno número de objetos precisa ser reciclado toda vez que o lixo é coletado, enquanto a característica da nova geração é que um grande número de objetos precisa ser reciclado toda vez que o lixo é coletado. Em seguida, o algoritmo de coleta mais adequado pode ser adotado de acordo com as características de diferentes gerações.
Atualmente, a maioria dos coletores de lixo adota o algoritmo de cópia para a nova geração, porque na nova geração, a maioria dos objetos precisa ser reciclada toda vez, ou seja, o número de operações que precisam ser copiadas é pequeno, mas, na realidade, o espaço da nova geração não é dividido de acordo com uma razão de 1: 1. De um modo geral, a nova geração é dividida em um espaço maior e dois espaços de sobrevivência menores (geralmente 8: 1: 1). Cada vez que o espaço do Éden e um dos espaços sobreviventes são usados, quando a reciclagem, os objetos que ainda sobrevivem no Éden e Survivor são copiados para outro espaço de sobrevivente, e depois o Éden e os espaços sobreviventes que acabam de ser utilizados são limpos.
Como a velhice é que apenas um pequeno número de objetos é reciclado toda vez, o algoritmo de compacto de marca é geralmente usado.
A análise breve acima do modelo de memória Java e da coleta de lixo é todo o conteúdo que compartilho com você. Espero que você possa lhe dar uma referência e espero que você possa apoiar mais o wulin.com.