关于JVM 的堆(heap)、栈(stack)方法区的详解

java中JVM虚拟机的内存可以分为3个区,堆区(heap)、栈区(stack)、方法区method

    Stack栈区:

    1、栈是什么

    栈也叫栈内存,主管java的程序运行,是在线程创建的时候创建,他的生命周期是跟随线程的生命周期 ,线程结束内存也就释放。对于栈来说不存在垃圾回收问题,只要线程一结束对应的栈就结束,生命周期和线程一致,是线程私有的。

    2、栈存储什么

   在栈中主要保存三类数据

   本地变量(Local Variables):输入参数和输出参数以及方法内的变量

   栈操作(Operand Stack):记录入栈、出栈的操作

   栈帧数据(Frame Data):包括类文件、方法等

    3、栈运行的原理

    栈中的数据都是以栈帧(Frame Data)的格式存在,栈帧是一个内存区块,是一个数据集,是一个有关方法和运行其数据的数据集,但一个方法A被调用时就产生了一个栈帧F1,并被压入到栈中,A方法又调用了B方法,于是产生了栈帧F2也被压入了栈中,B方法又调用了C方法,于是产生了栈帧F3……,依次执行完毕后,先弹出后进的……F3栈帧,再弹出F2栈帧,最后弹出F1栈帧。

遵循“先进后出,后进先出”的原则。

    Heap堆区:

     堆这块区域是JVM中最大的,应用的对象和数据都是存在这个区域,这个区域也是线程共享的,也是gc主要回收区,一个JVM实例只存在一个堆内存,堆内存的大小是可以调节的,类加载器读取了类文件之后,需要把类、方法、常变量放到堆内存中,以方便执行器执行,堆内存又分为三个部分

关于JVM 的堆(heap)、栈(stack)方法区的详解_第1张图片

① 新生区

     新生区是类的诞生、成长、消亡的区域,一个类在这里产生,应用,最后被垃圾回收器收集,结束生命。新生区又分为两部分:伊甸区(Eden space)和幸存者区(Survivor pace),所有的类都是在伊甸区被new出来的。幸存区有两个:0区(Survivor 0 space)和1区(Survivor 1 space)。当伊甸园的空间用完时,程序又需要创建对象,JVM的垃圾回收器将对伊甸园进行垃圾回收(Minor GC),将伊甸园中的剩余对象移动到幸存0区。若幸存0区也满了,再对该区进行垃圾回收,然后移动到1区。那如果1去也满了呢?再移动到养老区。若养老区也满了,那么这个时候将产生Major GC(FullGCC),进行养老区的内存清理。若养老区执行Full GC 之后发现依然无法进行对象的保存,就会产生OOM异常“OutOfMemoryError”。

如果出现java.lang.OutOfMemoryError: Java heap space异常,说明Java虚拟机的堆内存不够。原因有二:

a.Java虚拟机的堆内存设置不够,可以通过参数-Xms、-Xmx来调整。

b.代码中创建了大量大对象,并且长时间不能被垃圾收集器收集(存在被引用)。

② 养老区

养老区用于保存从新生区筛选出来的 JAVA 对象,一般池对象都在这个区域活跃。

③ 永久区

      永久存储区是一个常驻内存区域,用于存放JDK自身所携带的 Class,Interface 的元数据,也就是说它存储的是运行环境必须的类信息,被装载进此区域的数据是不会被垃圾回收器回收掉的,关闭 JVM 才会释放此区域所占用的内存。

如果出现java.lang.OutOfMemoryError: PermGen space,说明是Java虚拟机对永久代Perm内存设置不够。原因有二:

a. 程序启动需要加载大量的第三方jar包。例如:在一个Tomcat下部署了太多的应用。

b. 大量动态反射生成的类不断被加载,最终导致Perm区被占满。

说明:

Jdk1.6及之前:常量池分配在永久代 。

Jdk1.7:有,但已经逐步“去永久代” 。

Jdk1.8及之后:无(java.lang.OutOfMemoryError: PermGen space,这种错误将不会出现在JDK1.8中)。

方法区:
1.又叫静态区,跟堆一样,被所有的线程共享。方法区包含所有的class和static变量。
2.方法区中包含的都是在整个程序中永远唯一的元素,如class,static变量。

 

 

 

你可能感兴趣的:(Java基础)