java虚拟机
Java内存结构,分区,每个区放置什么
程序计数器:(线程私有)当前线程所执行的字节码的行号指示器,通过改变这个计数器的值来选取下一条需要执行的字节码的指令,以程序中分支、循环和跳转等流程的控制都离不开这个计数器的指示。
虚拟机栈:(线程私有),每个方法在执行时都会创建一个栈桢,用于存储局部变量表、操作数栈、动态链接和方法出口等信息。一个方法从调用到执行完成的过程,对应的栈桢在虚拟机栈的进出过程。当线程结束时,虚拟机栈中的数据会被自动的释放。
局部变量表:基本数据类型、对象的引用、返回地址,局部变量表锁需要的内存空间是在程序编译时就已经会被确定好的。
本地方法栈:(线程私有)虚拟机栈是为执行java方法所服务的,而本地方法栈是为了虚拟机使用到的本地方法锁服务的。
堆区:(线程共享)java堆是被所有的线程所共享的一片区域,所有的对象的实例和数组都会在堆区尽心分配。java堆细分:新生代和老年代;也可能会划分出多个线程锁共享额分配缓冲区TLAB;
Java堆可以在物理上不连续的内存空间中,只要逻辑上连续就可以。
方法区:(线程共享)存储已经被虚拟机加载过的类的信息、常量、静态变量和及时编译器编译后的代码。在方法区中一个区域叫做:运行时常量池,用于存放编译后生成的字面量和符号的引用。
堆的分代
(1)年轻代:
所有新生成的对象首先都是放在年轻代的。年轻代的目标就是尽可能快速的收集掉那些生命周期短的对象。年轻代分三个区。一个Eden区,两个Survivor区(一般而言)。
大部分对象在Eden区中生成。当Eden区满时,还存活的对象将被复制到Survivor区(两个中的一个),当一个Survivor区满时,此区的存活对象将被复制到另外一个Survivor区,当另一个Survivor区也满了的时候,从前一个Survivor区复制过来的并且此时还存活的对象,将被复制“年老区(Tenured)”。
(2)年老代:
在年轻代中经历了N(可配置)次垃圾回收后仍然存活的对象,就会被放到年老代中。因此,可以认为年老代中存放的都是一些生命周期较长的对象。
(3)持久代:
用于存放静态数据,如 Java Class, Method 等。持久代对垃圾回收没有显著影响。