1. 运行时数据区
1.1 程序计数器
可以理解为当前线程所执行的字节码的行号指示器,字节码解释器工作时就是通过改变这个计数器的值来选取下一条需要执行的字节码指令,它是程序控制流的指示器。
注意:1.在任何一个确定的时刻,一个处理器都会只执行一条线程中的指令。java虚拟机中的多线程是通过线程轮流切换,分配处理器执行时间的方式来实现的。为了线程切换后能恢复到正确的执行位置,每条线程都需要有一个独立的程序计数器,独立存储,互不影响,这类内存区域叫"线程私有"的内存。
2.若线程执行一个java方法,计数器就会记录正在执行的虚拟机字节码指令的地址;若正在执行的是本地Native方法,这个计数器的值则应为undefined,这也是内存区域唯一一个没有任何OutOfMemoryError情况的区域。
1.2 java虚拟机栈
描述的是方法执行的线程内存模型:每个方法被执行的时候,java虚拟机都会创建一个栈帧用于存储局部变量表,操作数栈,动态连接,方法出口等信息,直至方法出栈执行完毕。
和程序计数器一样,也是线程私有的,生命周期与线程相同。
局部变量表存放:基本数据类型(boolean,byte,char,short,int,float,long,duble),对象引用和returnAddress类型。long,double占用两个局部变量槽,其余占用一个。
局部变量表所需要的内存空间在编译时期完成分配,运行时不能改变,所以,stackOverflowError异常:线程请求的深度大于虚拟机所允许的深度。
1.3 本地方法栈
与虚拟机栈作用相同,但调用的对象是Native方法。
HotSpot虚拟机直接把本地方法栈和虚拟机栈合二为一。
1.4 堆
作用范围:所有线程共享;
目的:存放对象实例;
包含:新生代,老年代,永久代,Eden空间,Survivor空间等。(todo 待完善)
大小可扩展:通过参数(-Xmx和-Xms)设定。
1.5 方法区
作用范围:所有线程;
目的:存放被虚拟机加载的类型信息,常量,静态变量,即时编译器编译后的代码缓存等数据。
1.6 运行时常量池
本质:方法区的一部分;
目的:存放描述class文件的常量池表(存放编译时生成的各种字面量与符号引用),注:描述class文件的信息还包含类的版本,字段,方法,接口,但这里只有常量池表在类加载后存放在运行时常量池。
1.7 直接内存
本质:并非虚拟机运行时数据区的一部分
在JDK1.4中新加入了NIO类,它可以直接使用Native函数库直接分配堆外内存,然后通过java堆里面的DirectByteBuffer对象作为这块内存的引用进行操作,避免了java堆和Native堆中来回复制数据,从而显著提高性能。
通过-xmx等参数设置Jvm内存空间时,不要忽略直接内存,两者的和不能超过本机总内存。
原文:https://www.cnblogs.com/hujunwei/p/14588296.html