A especificação Java Virtual Machine estipula que a memória da JVM é dividida em vários blocos, como pilha, pilha, contador de programas, área de método etc. Na implementação da JVM de hotspot, a memória do heap é dividida em três partes, a nova geração, a idade antiga e a banda persistente. A banda persistente implementa a área de método especificada na especificação e diferentes partes do modelo de memória terão erros correspondentes do OrofMemoryError. Em seguida, vamos discutir isso separadamente. Acredito que a maioria dos desenvolvedores encontrou esse erro, e as razões para esse erro são causadas principalmente pelos seguintes motivos:
A memória da JVM é muito pequena e o programa não é apertado, resultando em muito lixo.
Existem várias causas comuns de exceções do OrofMemoryError:
Solicitações de erro comum para este erro:
StackOverflowerRor
O Stack Overflow lança um erro java.lang.stackoverflowerror. Isso ocorre porque a profundidade da pilha excede a profundidade máxima permitida pela máquina virtual quando o método está em execução. Essa situação geralmente ocorre devido a erros do programa. Por exemplo, escrever uma recursão morta pode causar essa situação. Vamos simular o excesso de memória nessa situação através de uma parte do código.
importar java.util.*; importar java.lang.*; public class OomTest {public void StackOverflowMethod () {StackOverflowMethod (); } public static void main (string ... args) {oomtest oom = new oomtest (); oom.stackOverflowMethod (); }} Executar o código acima lançará a seguinte exceção:
Exceção no tópico "Main" java.lang.stackOverflowerRor em oomtest.stackoverflowmethod (oomtest.java:6)
Overflow de heap (OrofMemoryError: Java Heap Space)
Quando a memória da heap transborda, a máquina virtual lança java.lang.outOfMemoryError: Java Heap Space. Quando isso acontece, precisamos analisá-lo especificamente com base no arquivo de despejo gerado quando a memória transborda (-xx: +heapdumtonouTofMemoryErrorJVM Parâmetro de inicialização precisa ser adicionado). Quando esse problema ocorre, pode ser um vazamento de memória ou um excesso de memória.
Se vazarem a memória, precisamos descobrir como o objeto vazado é referenciado pela raiz GC e analisar a causa do vazamento através da cadeia de referência.
Se houver um problema de transbordamento de memória, geralmente é porque o programa precisa de mais memória do que a memória que configuramos para a máquina virtual. Nesse caso, podemos usar o -xmx para resolver esse problema.
Abaixo, demonstramos o transbordamento desta situação através do seguinte código:
importar java.util.*; importar java.lang.*; public class Oomtest {public static void main (string ... args) {list <byte []> buffer = new ArrayList <byte []> (); buffer.add (novo byte [10*1024*1024]); }} Executamos o código acima através do seguinte comando:
java -verbose: gc -xmn10m -xms20m -xmx20m -xx:+printgc oomtest
O programa insere as seguintes informações:
[GC 1180K-> 366K (19456K), 0,0037311 Secs] [GC completo 366k-> 330K (19456K), 0,0098740 segs] [GC 330K-> 292K (19456), 0,00904444 Scines em Thread "292k (19456), 0,00904444 Scines em seguida" JAVAMA (19456k). Oomtest.main (oomtest.java:7)
A partir dos resultados em execução, podemos ver que a JVM realizou GC menor uma vez e duas vezes maior GC. A partir da saída do GC principal, pode -se observar que a taxa de uso da área antiga após o GC é de 134k, e a matriz de bytes é de 10m, o que aumenta para ser maior que o espaço da geração antiga, portanto, uma exceção é lançada. Se -xms21m e -xmx21m forem ajustados, a operação GC não será acionada e não haverá exceção.
Através do experimento acima, uma conclusão foi verificada de lado: quando o objeto é maior que a memória restante da nova geração, ela será colocada diretamente na velhice. Quando a memória restante da velhice ainda não puder ser abaixada, a coleta de lixo será acionada. Se ainda não puder ser abaixado após a coleta, uma exceção de transbordamento de memória será lançada.
Espaço permgen
Sabemos que o Hotspot JVM implementa a área do método na especificação da máquina virtual Java por meio de bandas persistentes, e o pool constante de tempo de execução é armazenado na área do método. Portanto, o transbordamento persistente da banda pode ser o excesso de pool constante de tempo de execução, ou os objetos de classe salvos na área do método não são reciclados no tempo ou a memória ocupada pelas informações de classe excede nossa configuração. Quando a banda de persistência transborda, java.lang.outofmemoryerror: o espaço permgen é jogado.
Posso experimentar esse problema nos seguintes cenários ao trabalhar.
Ao usar a implantação a quente de alguns servidores de aplicativos, encontraremos a implantação a quente várias vezes e encontraremos que a memória transborque. Isso ocorre porque, após cada implantação a quente, a classe original não foi desinstalada.
Se o aplicativo em si for maior e envolver mais bibliotecas de classes, esse problema também pode ocorrer quando a memória que alocamos para a banda persistente (definida por -xx: PermSize e -xx: maxpermsize) é relativamente pequena.
Algumas estruturas de terceiros, como Spring e Hibernate, implementam algumas funções aprimoradas por meio da tecnologia de geração de bytecode (como o CGLIB), que podem exigir uma área de método maior para armazenar arquivos de classe gerados dinamicamente.
Sabemos que as constantes de cordas em Java são colocadas em uma piscina constante. Quando o método string.intern () é executado, ele verificará se os objetos iguais a essa string são armazenados no pool constante. Se existir, retorne diretamente uma referência ao objeto no pool constante. Se não existir, adicione esta string ao pool constante primeiro e depois retorne a referência à string. Em seguida, podemos simular o transbordamento da área constante durante o tempo de execução pelo método String.intern. Vamos simular esta situação através do seguinte código:
importar java.util.*; importar java.lang.*; public class Oomtest {public static void main (string ... args) {list <string> list = new ArrayList <String> (); while (true) {list.add (uuid.randomuuid (). ToString (). Intern ()); }}}Executamos o código acima através do seguinte comando:
java -verbose: gc -xmn5m -xms10m -xmx10m -xx: maxpermsize = 1m -xx:+printgc oomtestest
A entrada após a execução é mostrada na figura abaixo:
Exceção no tópico "Main" java.lang.outOfMemoryError: Space Permgen em java.lang.string.intern (método nativo) em oomtest.main (oomtest.java:8)
Através do código acima, simulamos com sucesso o transbordamento constante do pool durante o tempo de execução. A partir do espaço permgen da saída, podemos ver que a banda persistente está realmente transbordando, o que também verifica a afirmação de que o ponto de acesso JVM implementa a área do método por meio da banda persistente, como mencionado anteriormente.
OrofMemoryError: Incapaz de criar threads nativos
Finalmente, vamos dar uma olhada no erro java.lang.outOfMemoryError: Não é possível criar um thread NatVie. Quando isso acontece, geralmente é causado pelas duas situações a seguir:
O número de threads criados pelo programa excede o limite do sistema operacional. Para sistemas Linux, podemos ver essa limitação através do ULIMIT -U.
A memória alocada para a máquina virtual é muito grande, resultando em muito pouca memória nativa necessária ao criar threads. Todos sabemos que o sistema operacional tem um limite para a memória de cada processo. Ao iniciar a JVM, é equivalente a iniciar um processo. Se um de nossos processos ocupar 4G de memória, a memória restante calculada através da fórmula a seguir é a memória que pode ser usada ao criar uma pilha de thread. Memória total disponível para pilha de thread = 4g- (valor de -xmx)-(-xx: valor de maxpermsize)-A memória ocupada pelo contador do programa é mostrada pela fórmula acima que quanto maiores os valores de -xmx e maxpermsize, menor o espaço disponível para a pilha de roscas. Quando a capacidade da pilha configurada pelo parâmetro -xss permanece inalterada, quanto menor o número de threads que podem ser criados. Portanto, se for impossível criar um thread nativo devido a essa situação, aumentamos a memória total ocupada pelo processo ou reduzimos -xmx ou -xss para alcançar o objetivo de criar mais threads.
O exposto acima é todo o conteúdo deste artigo. Espero que seja útil para o aprendizado de todos e espero que todos apoiem mais o wulin.com.