A pilha Java é usada para armazenar instâncias de objetos. Portanto, se criarmos continuamente objetos e garantirmos que haja um caminho acessível entre a raiz GC e o objeto criado para evitar que o objeto seja coletado de lixo, então quando muitos objetos forem criados, ela causará memória de heap insuficiente, o que aumentará uma exceção de excesso de MemoryError.
/** * @author xiongyongshun * vm args: java -xms10m -xmx10m -xx:+heapdumpoponoutOfMemoryError */public class OrofmemoryerRorTest {public static void main (string [] args) {list <Tegerger> int i = 0; while (true) {list.add (i ++); }}}O exposto acima é um código que eleva uma exceção do OrofMemoryError. Podemos ver que ele impede que o objeto seja coletado com lixo, criando constantemente e salvando o objeto na lista. Portanto, quando houver muitos objetos, a memória da pilha transbordará.
Através de java -xms10m -xmx10m -xx:+heapdumtonoutOfMemoryError, definimos a memória da heap como 10 megabytes e usamos o parâmetro -xx:+heapdumtonOtofMemoryError para fazer a impressão da JVM em torno da memória.
Depois de compilar e executar o código acima, a saída a seguir será:
>>> java -xms10m -xmx10m -xx:+heapdumtonoutfmemoryerror com.test.outOfMemoryerRorTest 16-10-02 23: 35java.lang.outOfMemoryError: Java ... 0.125 ss] Exceção no tópico "Main" java.lang.outofmemoryerror: Java Heap Space em java.util.arrays.copyof (Arrays.java:3210) em Java.util.aril.arrays.copyof (Arrays.java:3181) em java.util.arraylist.ensureExplicitCapacity (ArrayList.java:235) em java.util.arraylist.ensureCapacityInternal (Arraylist.java:227) em java.util.arraylist.add (ArrayList.Java:48) com.test.outofmemoryerRortest.main (ourofmemoryerRortest.java:15)
Java StackoverflowerRor
Sabemos que existe uma área de memória chamada pilha de máquina virtual na área de dados de tempo de execução da JVM. A função dessa área é: cada método criará um quadro de pilha quando for executado, usado para armazenar informações como tabelas de variáveis locais, pilhas de operando, saídas de método etc.
Portanto, podemos criar uma chamada recursiva infinitamente recursiva. Quando a profundidade recursiva for muito grande, o espaço da pilha será esgotado, o que levará a uma exceção de StackOverFlowerRor.
Aqui está o código específico:
/** * @author xiongyongshun * vm args: java -xss64k */classe pública outfmemoryerRortest {public static void main (string [] args) {sTackoutOfMemoryError (1); } public static void StackOutOfMemoryError (int de profundidade) {Depth ++; StackoutOfMemoryError (profundidade); }}Depois de compilar e executar o código acima, as seguintes informações de exceção serão emitidas:
Exceção no tópico "Main" java.lang.stackoverflowerror em com.test.outofmemoryerRortest.stackoutofmemoryError (ourofmemoryerRortest.java:27)
Overflow de memória na área do método
Observe que, como o JDK8 removeu a geração permanente e a substituiu pelo Metaspace, no JDK8, nenhum dos dois exemplos a seguir causará java.lang.outOfMemoryError: exceção do espaço permgen.
Constantes transbordamentos de piscina durante o tempo de execução
No Java 1.6 e nas versões anteriores da JVM de ponto de acesso, existe um conceito de geração permanente, ou seja, o mecanismo de coleta de geração de GC é estendido para a área do método. Na área do método, uma parte da memória é usada para armazenar pools constantes. Portanto, se houver muitas constantes no código, a memória do pool constante será esgotada, resultando em excesso de memória. Então, como adicionar um grande número de constantes à piscina constante? No momento, você precisa confiar no método string.intern (). A função do método string.intern () é: se o valor dessa string já existir no pool constante, esse método retornará a referência à sequência correspondente no pool constante; Caso contrário, adicione o valor contido nesta sequência ao pool constante e retorne a referência a este objeto String. No JDK 1.6 e nas versões anteriores, o pool constante é alocado na geração permanente. Portanto, podemos limitar indiretamente o tamanho do pool constante, definindo os parâmetros "-xx: PermSize" e "-xx: maxPermsize".
Observe que a distribuição de memória do método string.intern () mencionada acima e o pool constante é apenas para versões JDK 1.6 e anteriores. No JDK 1.7 ou superior, o layout da memória é ligeiramente diferente porque o conceito de geração permanente é removido.
A seguir, é apresentado um exemplo de código para implementar o excesso de memória de pools constantes:
/** * @Author xiongyongshun * vm args: -xx: PermSize = 10m -xx: maxpermsize = 10m */public class RunTimeConstantPoolOoMtest {public static void main (string [] args) {list <tring> list = new Arraylist <tring> (); int i = 0; while (true) {list.add (string.valueof (i ++). Intern ()); }}}Vemos que, neste exemplo, ele está usando com precisão o método string.intern () para adicionar um grande número de constantes de string ao pool constante, o que leva ao excesso de memória do pool constante.
Compilamos e executamos o código acima através do JDK1.6, e a seguinte saída será:
Exceção no thread "main" java.lang.outOfMemoryError: Space Permgen em java.lang.string.intern (método nativo) em com.test.runtimeConstantpooloomtest.main (runtimeconstantpooloomtest.java:16)
Deve -se notar que, se o código acima for compilado e executado através do JDK1.8, haverá o seguinte aviso e nenhuma exceção será gerada:
>>> java -xx: PermSize = 10m -xx: maxpermsize = 10m com.test.runtimeConstantPoolOoMtest 16-10-03 0: 23Java HotSpot (TM) de 64 bits VM Aviso: Opção de ignorando Permsize = 10m; O suporte foi removido em 8.0 Hotspot Java (TM) de 64 bits VM Aviso: Ignorando a opção maxpermsize = 10m; O suporte foi removido em 8.0
Transbordamento de memória na área do método
A função da área do método é armazenar as informações relevantes da classe, como nomes de classe, modificadores de acesso a classes, descrições de campo, descrições de métodos etc. Portanto, se a área do método for muito pequena e muitas classes são carregadas, o transbordamento de memória da área do método.
// vm args: -xx: PermSize = 10m -xx: maxpermsize = 10mpublic class MethodareaoomTest {public static void main (string [] args) {while (true) {intensificador intensificador = new intensancer (); intensificador.SetSuperclass (MethodareaoomTest.class); intensificador.setUseCache (false); intensancer.setCallback (new MetodIntercept () {public Object Intercept (objeto o, método do método, objeto [] Objetos, MethodProxy MethodProxy) lança jogável {retornar métodProxy.invokesuper (o, objetos);}}); intensificador.create (); }}}No código acima, usamos o CGLIB para gerar dinamicamente um grande número de classes. No JDK6, a execução do código acima gerará um OrofMemoryError: Permgen Space Exception:
/System/library/frameworks/javavm.framework/versions/1.6/home/bin/java-jar -xx: PermSize = 10m -xx: maxpermsize = 10m Target/test-1.0-snapshot.jar
O resultado da saída é o seguinte:
Causado por: java.lang.outofMemoryError: espaço permgen em java.lang.classloader.defineclass1 (método nativo) em java.lang.classloader.defineclassCond (classloader.java:637) em java.lang.cllassLoadeR.DefinEnCond (ClassLoader.Java:637) em java.lang.cllassloadR.DefinEnCond (ClassLoadel) em Java.CLASSCONDLEFINCOND (CLASSPLOTER.JAVA:637) em
Metaspace Memory Overflow
Na seção de transbordamento de memória de transbordamento de memória na área do método, mencionamos que o JDK8 não possui conceito de geração permanente; portanto, esses dois exemplos não alcançaram o efeito esperado no JDK8. Então, no JDK8, existem erros como estouro de memória na área de métodos? Claro, alguns. No JDK8, a área do Metaspace é usada para armazenar informações relacionadas à aula; portanto, quando o Metaspace é insuficiente, será lançado um java.lang.outOfMemoryError: a exceção do Metaspace será lançada.
Vamos dar o exemplo mencionado acima como exemplo:
// vm args: -xx: maxmetaspacesize = 10mpublic class MethodareaoomTest {public static void main (string [] args) {while (true) {intensificador intensificador = new aprimor (); intensificador.SetSuperclass (MethodareaoomTest.class); intensificador.setUseCache (false); intensancer.setCallback (new MetodIntercept () {public Object Intercept (objeto o, método do método, objeto [] Objetos, MethodProxy MethodProxy) lança jogável {retornar métodProxy.invokesuper (o, objetos);}}); intensificador.create (); }}}A parte do código deste exemplo não foi alterada. A única diferença é que precisamos usar o JDK8 para executar este código e definir o parâmetro -xx: maxmetaspacesize = 10m. Este parâmetro diz à JVM que o tamanho máximo do metapacial é de 10m.
Em seguida, usamos o JDK8 para compilar e executar este exemplo, e produzimos a seguinte exceção:
>>> java -jar -xx: maxmetaspacesize = 10m Target/test-1.0 -snapshot.jarexception em thread "main" java.lang.outOfMemoryError: metapace em net.sf.cglib.core.abstractClassGenerator.GeRaSpace (abstractClastClassGenerador net.sf.cglib.proxy.enhancer.Generate (aprimor.java:492) em net.sf.cglib.core.abstractclassGenerator $ classeLoaderData.get.abstractCreator.java:114) em net.sf.cglib.core.abstra. em net.sf.cglib.proxy.enhancer.createhelper (intensificador.java:480) em net.sf.cglib.proxy.enhancer.create (intensancer.java:305) em com.test.methodareaoomtest.maiin (métodaraooMestest.javest.javaest.javaest.javaest.javaest.javaest.javaest.javaest.javaest.javaest.javaest.javaest.javaest.javaest.test.methodareaooomtest.maiin (métodaraooMestest.javest.javaest.javaest.javal
Resumir
O exposto acima é sobre exceções e exemplos de código de excesso de memória comum neste artigo, espero que seja útil para todos. Amigos interessados podem continuar se referindo a outros tópicos relacionados neste site. Se houver alguma falha, deixe uma mensagem para apontá -la. Obrigado amigos pelo seu apoio para este site!