Java8中内存模型PermGen Metaspace的示例分析

  介绍

这篇文章主要介绍了Java8中内存模型PermGen Metaspace的示例分析,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获、下面让小编带着大家一起了解一下。

一、JVM内存模型

根据JVM规范,JVM内存共分为虚拟机栈,堆,方法区,程序计数器,本地方法栈五个部分。

 Java8中内存模型PermGen Metaspace的示例分析

1,虚拟机栈:每个线程有一个私有的栈,随着线程的创建而创建。栈里面存着的是一种叫“栈帧”的东西,每个方法会创建一个栈帧,栈帧中存放了局部变量表(基本数据类型和对象引用),操作数栈,方法出口等信息。栈的大小可以固定也可以动态扩展。当栈调用深度大于JVM所允许的范围,会抛出StackOverflowError的错误,不过这个深度范围不是一个恒定的值,我们通过下面这段程序可以测试一下这个结果:

栈溢出测试源码:

package  com.paddx.test.memory;   ,   public  class  StackErrorMock  {   private 才能static  int  index =, 1;   ,   public 才能;void 调用(){   ,,,指数+ +;   ,,,叫();   ,,}   ,   public 才能;static  void  main (String [], args), {   ,,,StackErrorMock  mock =, new  StackErrorMock ();   ,,,try  {   ,,,,,mock.call ();   ,,,}catch  (Throwable  e) {   ,,,,,System.out.println (“Stack  deep :,“+指数);   ,,,,,e.printStackTrace ();   ,,,}   ,,}   }

代码段1

运行三次,可以看出每次栈的深度都是不一样的,输出结果如下。

 Java8中内存模型PermGen Metaspace的示例分析

至于红色框里的值是怎么出来的,就需要深入到JVM的源码中才能探讨,这里不作详细阐述。

虚拟机栈除了上述错误外,还有另一种错误,那就是当申请不到空间时,会抛出OutOfMemoryError。这里有一个小细节需要注意,捉捕获的是Throwable,而不是例外。因为StackOverflowError和OutOfMemoryError都不属于异常的子类。

2,本地方法栈:

这部分主要与虚拟机用到的原生方法相关,一般情况下,Java应用程序员并不需要关心这部分的内容。

3,电脑寄存器:

电脑寄存器,也叫程序计数器.JVM支持多个线程同时运行,每个线程都有自己的程序计数器。倘若当前执行的是JVM的方法,则该寄存器中保存当前执行指令的地址;倘若执行的是原生的方法,则电脑寄存器中为空。

4堆

堆内存是JVM所有线程共享的部分,在虚拟机启动的时候就已经创建。所有的对象和数组都在堆上进行分配。这部分空间可通过GC进行回收。当申请不到空间时会抛出OutOfMemoryError。下面我们简单的模拟一个堆内存溢出的情况:

package  com.paddx.test.memory;   ,   import  java.util.ArrayList;   import 并不知道;   ,   public  class  HeapOomMock  {   public 才能;static  void  main (String [], args), {   ,,,List

代码段2

运行上述代码,输出结果如下:

 Java8中内存模型PermGen Metaspace的示例分析

注意,这里我指定了堆内存的大小为16 m,所以这个地方显示的数=14(这个数字不是固定的),至于为什么会是14或其他数字,需要根据GC日志来判断,具体原因会在下篇文章中给大家解释。

5,方法区:

方法区也是所有线程共享。主要用于存储类的信息,常量池,方法数据,方法代码等。方法区逻辑上属于堆的一部分,但是为了与堆进行区分,通常又叫“非堆”。关于方法区内存溢出的问题会在下文中详细探讨。

二,PermGen(永久代)

绝大部分Java程序员应该都见过“java.lang.OutOfMemoryError: PermGenspace"这个异常。这里的“PermGen空间”其实指的就是方法区,不过方法区和“PermGen空间”又有着本质的区别。前者是JVM的规范,而后者则是JVM规范的一种实现,并且只有热点才有“PermGen空间”,而对于其他类型的虚拟机,如JRockit (Oracle), J9 (IBM)并没有“PermGen空间”。由于方法区主要存储类的相关信息,所以对于动态生成类的情况比较容易出现永久代的内存溢出。最典型的场景就是,在jsp页面比较多的情况,容易出现永久代内存溢出。我们现在通过动态生成类来模拟“PermGenspace”的内存溢出:

Java8中内存模型PermGen Metaspace的示例分析