Introdução
Qual é o ciclo de vida das variáveis definidas nos métodos java? É necessário esperar até o final do método para que o objeto criado seja reciclado?
Com esta pergunta, vamos dar uma olhada no artigo de hoje.
O ciclo de vida das variáveis locais
Em uma classe, os tipos de variáveis incluem variáveis de classe, variáveis de membro e variáveis locais.
Variáveis locais referem-se às variáveis definidas no método.Se definirmos uma variável no método, qual é o ciclo de vida desta variável?
por exemplo:
public void test(){
Object object = new Object();
doSomeThingElse(){
...
}
}
No método de teste acima, uma variável local do objeto é definida e, em seguida, outro método é executado.
Porque em Java, não podemos controlar diretamente o ciclo de vida de um objeto, e a coleta de objetos é realizada automaticamente pelo coletor de lixo.
De modo geral, este objeto permanecerá até o final de toda a execução do teste antes de ser reciclado.
Agora, consideramos um caso especial: se o método doSomeThingElse for um loop while e nunca terminar, o objeto criado será reciclado? Ou está sempre na memória?
Deixe-me falar sobre nossa conclusão primeiro, a JVM é muito inteligente e pode detectar essa situação e reciclar o objeto.
por exemplo
Para explicar melhor o problema, personalizamos um objeto Teste e imprimimos as informações correspondentes antes de ser criado e reciclado.
public static class Test {
public Test() {
System.out.println("创建对象 " + this);
}
public void test() {
System.out.println("测试对象 " + this);
}
@Override
protected void finalize() throws Throwable {
System.out.println("回收对象 " + this);
}
}
Em seguida, faça dois testes. O primeiro teste não tem um loop infinito e o segundo teste mantém um loop infinito. O loop é controlado por um sinalizador de variável volátil:
public static void main(String[] args) throws InterruptedException {
System.out.println("开始测试1");
resetFlag();
flag = true;
testLocalVariable();
System.out.println("等待Test1结束");
Thread.sleep(10000);
System.out.println("开始测试2");
flag = true;
testLocalVariable();
}
Dê uma olhada na definição do método testLocalVariable:
public static void testLocalVariable() {
Test test1 = new Test();
Test test2 = new Test();
while (flag) {
// 啥都不做
}
test1.test();
}
Em seguida, começamos outro thread para fazer o tempo GC. Agora que tudo está pronto, vamos executar:
开始测试1
创建对象 [com.flydean.LocalVariableReachability$Test@119d7047](mailto:com.flydean.LocalVariableReachability$Test@119d7047)
创建对象 [com.flydean.LocalVariableReachability$Test@776ec8df](mailto:com.flydean.LocalVariableReachability$Test@776ec8df)
回收对象 [com.flydean.LocalVariableReachability$Test@776ec8df](mailto:com.flydean.LocalVariableReachability$Test@776ec8df)
测试对象 [com.flydean.LocalVariableReachability$Test@119d7047](mailto:com.flydean.LocalVariableReachability$Test@119d7047)
等待Test1结束
回收对象 [com.flydean.LocalVariableReachability$Test@119d7047](mailto:com.flydean.LocalVariableReachability$Test@119d7047)
开始测试2
创建对象 [com.flydean.LocalVariableReachability$Test@4eec7777](mailto:com.flydean.LocalVariableReachability$Test@4eec7777)
创建对象 [com.flydean.LocalVariableReachability$Test@3b07d329](mailto:com.flydean.LocalVariableReachability$Test@3b07d329)
回收对象 [com.flydean.LocalVariableReachability$Test@3b07d329](mailto:com.flydean.LocalVariableReachability$Test@3b07d329)
Olhando para o resultado do teste 1 primeiro, podemos ver que o segundo objeto foi reciclado antes de chamar test1.test ().
Olhando o resultado do teste 2, podemos ver que o segundo objeto também foi reciclado.
Os resultados mostram que a JVM é inteligente o suficiente para otimizar o ciclo de vida das variáveis locais.
Razões para otimização
Vamos considerar, em que estágio a JVM otimiza o ciclo de vida das variáveis locais?
Obviamente, essa otimização não é feita durante a compilação, mas durante o tempo de execução.
Usamos -XX: + PrintAssembly para analisar o código de montagem:
Em primeiro lugar, aprendi minha linguagem assembly há muitos anos. Se houver erros na explicação, corrija-me.
Deixe-me falar sobre os dois conceitos rbx e r10 são ambos registradores de CPU de 64 bits e r10d são os 32 bits inferiores de r10.
Primeiro olhe para a caixa vermelha 1. A caixa vermelha 1 significa que o que está armazenado em rbx é um objeto Teste na classe LocalVariableReachability que definimos.
Observe a caixa vermelha 2. A caixa vermelha 2 significa que r10 agora salva uma instância da classe LocalVariableReachability.
A caixa vermelha 3 representa os objetos armazenados no ImmutableOopMap ao entrar no loop while.Você pode ver que nele há apenas r10 e rbx, ou seja, apenas a instância da classe e uma das instâncias Test.
O que é Red Box 4? A caixa vermelha 4 representa um ponto seguro, que é um ponto seguro durante a coleta de lixo. Neste ponto seguro, se houver objetos que não são mais usados, eles serão reciclados.
Como há apenas dois objetos em ImutableOopMap, a instância de teste restante será reciclada.