jvm内存学习
Jvm学习
一、Jvm内存划分
Jvm内存主要划分为以下几个模块
二、程序计数器(Program Counter Register)
程序计数器是线程私有的,每一个线程有一个。
与cpu中的pc寄存器相似,用来只是当前的线程执行到了字节码的哪一行。
当jvm当前执行的是一个java方法,则程序计数器记录的是当前放的字节码地址;如果执行的是一个本地方法,则程序计数器存放的是Undefined。
三、虚拟机栈(JVM Stack)
虚拟机栈是线程私有的,每一个线程有一个。
一个线程的每个方法被执行的时候,都会创建一个栈帧。
栈帧中有局部变量表,操作站,动态链接,方法出口等。
方法被调用时,栈帧入栈,方法执行完成时,栈帧出栈。
局部变量表中存储着方法的局部变量,包括基本类型,对象的引用,返回地址等。
在局部变量表中,只有long和double类型会占用2个局部变量空间(Slot,对于32位机器,一个Slot就是32个bit),其它都是1个Slot。
虚拟机栈定义了2中异常。当线程调用的栈深度超过了栈的最大深度,会抛出StatckOverFlowError异常。当虚拟机栈没有被固定大小时,会不停的申请内存扩展大小,直到达到最大内存,会有OutOfMemoryError异常。
四、本地方法栈(Native Method Statck)
本地方法栈是线程私有的,每一个线程有一个。
本地方法栈与虚拟机栈相似,唯一的区别是,虚拟机栈执行的是java方法,本地方法栈执行的native方法。但是在很多jvm中,两种栈是合在一起的。
五、堆区(Heap)
堆区是线程私有的,每一个线程有一个。
堆区大致分为两个区域,或者叫两代。一个叫年轻代,一个叫老年代。
年轻代存储的刚创建的对象,年轻代又分为两个区域,Eden(伊甸)区和Survivor(幸存)区,survivor区有两个。
① 对象刚刚被创建时,是分配在eden区的,eden区的内存是连续的,因此速度较快。
② 当eden区第一次满了之后,将会执行Minor GC,将过期的对象销毁,把幸存的对象复制到survivor0中(survivor0和survivor1总有一个是空的)。
③ 当eden再一次满了,再进行一次Minor GC,会将幸存的对象复制到survivor1中。
④ 并且会将survivor0中的过期对象销毁,够资格的晋级年老代,幸存的进入survivor1中。
⑤ 当两个survivor区来回切换了几次后,大于等于15次(这个值可配置-XX:MaxTenuringThreshold)的对象将会进入老年区。
六、方法区(Method Area)
方法区是各个线程共享的区域。
之前,Hotspot虚拟机把堆内存划分为 青年代,老年代,持久代。而方法区指的就是这个持久代。但其他大多数虚拟机都没有持久代,而Hotspot也已经取消了这个所谓持久代。
方法区,用于存储已经被虚拟机加载的类信息(即加载类时需要加载的信息,包括版本、field、方法、接口等信息)、final常量、静态变量、编译器即时编译的代码等。