O chefe me pediu para escrever um erro!

Prefácio

O título está correto, realmente me fez escrever um  bug!

Quando recebi essa demanda, não senti as menores ondas do coração e fiquei um pouco empolgado. Esta é a minha especialidade; finalmente posso escrever na vertical  bug .

Vamos dar uma olhada nos detalhes primeiro.De fato, o principal motivo é permitir que alguns servidores com baixa carga consumam recursos adicionais, como memória e CPU (para não mencionar o plano de fundo), para que sua carga possa ser aumentada.

Revisão de alocação de memória da JVM

Então, roubei um ônibus e escrevi o código, provavelmente da seguinte maneira:

Depois de escrever, eu estava pensando em uma pergunta: os mem objetos no código  serão reciclados imediatamente após a execução do método? Eu acho que haverá algumas pessoas que pensam que será reciclada depois que o método for executado.

Eu também fiz pesquisas e perguntei a alguns amigos; de fato, alguns deles acham que foi recuperado após a execução do método.

E os fatos? Eu fiz um experimento.

Usei os seguintes parâmetros de inicialização para iniciar o aplicativo agora.

java -Djava.rmi.server.hostname = 10.xx.xx.xx -Djava.security.policy 
 = jstatd.all.policy 
 -Dcom.sun.management.jmxremote.authenticate = false 
 -Dcom.sun.management.jmxremote. ssl = false 
 -Dcom.sun.management.jmxremote.port = 8888 -Xms4g -Xmx4g -jar bug-0.0.1-SNAPSHOT.jar

Para que eu possa conectar-me remotamente a este aplicativo através da porta JMX para observar as condições de memória e GC.

Se o método for concluído, o mem objeto será reciclado  quando eu alocar  250M memória; a memória terá uma curva clara e o GC também será executado.

Observe a curva de memória neste momento.

Você descobrirá que há realmente um aumento significativo, mas não foi recuperado imediatamente depois, mas permaneceu nesse nível da água. Ao mesmo tempo, não há resposta do GC à esquerda.

jstat mesmo acontece ao visualizar o layout da memória.

Não importa  YGC,FGC , é apenas que a proporção da área do Éden aumentou.Afinal, 250M de memória são alocados.

Como pode ser reciclado?

Eu aloquei dois 250M novamente e observei a curva de memória.

Verifica-se que o terceiro fuso Eden horário de 250M  é atingido, 98.83% portanto a Eden área de recuperação precisa ser gerada  quando for alocada novamente  YGC.

Ao mesmo tempo, a curva de memória também caiu.

Todo o processo de conversão é mostrado na figura:

Como a memória heap inicializada é  4G, a Eden área calculada  provavelmente é a  1092M memória.

Além Spring da 20% memória aproximada consumida pela  inicialização do aplicativo  e assim por diante, isso resultará na alocação de 250M de memória 3 vezes  YGC.

Vamos rever a questão agora:

mem Como o objeto não será coletado após a execução do método, quando será coletado?

De fato, lembre-se de uma coisa: o objeto precisa GC ser coletado quando o coletor de lixo ocorrer  ; não importa se o objeto é uma variável local ou global.

Através do experimento anterior, também descobrimos que os  objetos  que criamos serão recuperados apenas  quando o  Eden espaço for insuficiente  .YGCmem

Mas há realmente uma condição oculta aqui: ou seja, esse objeto é uma variável local. Se o objeto for uma variável global, ele ainda não poderá ser reciclado.

Ou seja, costumamos dizer que o objeto está inacessível, de modo que o objeto inacessível  GC será considerado como o objeto a ser reciclado quando ocorrer.

Após muita consideração, por que algumas pessoas pensam que as variáveis ​​locais serão recuperadas após a execução do método?

Eu acho que isso deve ser confuso, de fato, o que é recuperado após a execução do método 栈帧.

O resultado mais direto é que  mem o objeto não é mais referenciado. Mas, sem citação, isso não significa que será reciclado imediatamente, ou seja, as necessidades acima mencionadas  GC serão recicladas.

Portanto, o algoritmo de análise de acessibilidade usado para os objetos inacessíveis mencionados acima é usado para indicar quais objetos precisam ser reciclados.

Quando o objeto não é referenciado, é considerado inacessível.

Aqui está uma imagem clara:

Após a execução do método, os  mem objetos nele são equivalentes aos da figura e  Object 5, portanto GC , serão reciclados no  momento.

Dar prioridade a objetos na área do Éden

De fato, pode-se ver no exemplo acima que os objetos são preferencialmente alocados na área Eden da nova geração, mas há uma premissa de que o objeto não pode ser muito grande.

O conteúdo relacionado também foi escrito antes:

Objetos grandes vão diretamente para a geração antiga

Os objetos grandes são alocados diretamente para a geração antiga (quanto ao tamanho, ele pode ser configurado através de parâmetros).

Quando aloquei diretamente 1000M de memória, porque a área Eden não pode ser instalada diretamente, ela foi alocada na geração antiga.

Pode-se ver que  Eden quase não há mudanças na área, mas a geração antiga aumentou 37% .De acordo com a memória da geração antiga 2730M calculada anteriormente,  é quase a mesma que  1000M a memória.

Visualização de memória do Linux

De volta a esse tempo, preciso concluir a demanda: aumentar a memória do servidor e o consumo da CPU.

Felizmente, a própria CPU tem uma certa quantidade de uso e, ao mesmo tempo, cada objeto criado consumirá alguma CPU.

Principalmente a memória, vamos primeiro olhar para a memória antes de iniciar este aplicativo.

Provavelmente usava apenas 3G de memória.

Após iniciar o aplicativo, ele consome apenas 600M de memória.

Para atender à demanda, preciso alocar um pouco de memória, mas aqui preciso prestar atenção.

A memória não pode ser alocada o tempo todo, o que fará com que a carga da CPU seja muito alta e, ao mesmo tempo, a memória não será particularmente ocupada devido à reciclagem do GC.

Portanto, preciso de uma pequena quantidade de alocação para que a maioria dos objetos da nova geração precise ser mantida em 80% ou 90% para não ser reciclada.

Ao mesmo tempo, alguns objetos grandes precisam ser alocados para a geração antiga, e o uso da geração antiga deve ser mantido em 80% ou 90%.

Dessa maneira, a memória heap 4G pode ser usada ao máximo.

Então eu fiz o seguinte:

  • Primeiro, aloque alguns objetos pequenos na nova geração (800M) para manter a nova geração em 90%
  • Em seguida, foi alocado 老年代内 *(100%-已使用的28%);也就是 2730*60%=1638M para que a geração antiga também estivesse em torno de 90%.

O efeito é como acima.

O mais importante é GC que isso não aconteceu uma vez  e alcançou meu objetivo.

Eventualmente, a memória consumiu cerca de 3,5G.

Sumário

Embora desta vez a demanda seja relativamente estranha, JVM ainda não é tão fácil controlar a alocação de memória com precisão  .

Você precisa ter um certo entendimento de seu layout de memória e reciclagem. O processo de escrever esse bug realmente aprofundou a impressão. Se for útil para você, não seja mesquinho com seus gostos e compartilhamento.

 

Acho que você gosta

Origin www.cnblogs.com/xiaobin123/p/12729968.html
Recomendado
Clasificación