运行时数据区域分为:
1.程序计数器(Program Counter Register)
程序计数器是一块较小的内存空间,它可以看作是当前线程所执行的字节码行号指示器。字节码解释器工作时就是通过改变这个计数器的值来选取下一条需要执行的字节码指令,分支、循环、跳转、异常处理、线程恢复等基础功能都需要依靠这个计数器来完成。
2.虚拟机栈
1.线程私有,生命周期与线程相同。虚拟机栈描述的是java方法执行的内存模型,每个方法在执行的时候都会创建一个栈帧。用于存储局部变量表、操作数栈、动态链接、方法出口等信息。每一个方法从调用到执行完成的过程,就对应着一个栈帧在虚拟机栈中从入栈到出栈的一个过程。
2.局部变量表存放的数据类型:基本数据类型(byte、short、int、long、float、duble、char、boolean),对象引用
3.会抛出StackOverflowError和OutOfMemoryError异常
3.本地方法栈
1.与虚拟机栈作用相似,区别是虚拟机栈为虚拟机执行java方法服务,而本地方法栈则为虚拟机使用到的Native方法服务。
2.同样会抛出StackOverflowError和OutOfMemoryError异常。
4.堆
1.堆是虚拟机管理的内存中最大的一块。
2.堆被所有线程共享。
3.几乎所有的对象实例都在这里分配内存。
4.Java堆是垃圾收集管理的主要区域。内存回收角度来看,由于现在收集器基本都采用分代收集算法,所以堆中还可细分为:
a.新生代。 新生代包括Eden空间、To Survivor空间、Form Survivor空间。默认比例是8:1 Eden区为8。由于有两个 Survivor,所以每个Survivor占比是1:10
b.老年代
5.通过-Xms和-Xmx来设置堆的大小。
6.当堆内中没有可用内存为实例分配时,并且堆内存也无法再扩展,将会抛出OutOfMemoryError异常
5.方法区(jdk1.7是方法区,jdk1.8更换为元空间)
1.与堆一样,被所有线程共享。
2.存储数据:已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。
3.设置大小:
jdk1.7 :
-XX:PermSize 方法区初始大小
-XX:MaxPermSize 方法区最大大小
超过这个大小将会抛出OutOfMemoryError异常:java.lang.OutOfMemoryError:PermGen
jdk1.8:
-XX:MetaspaceSize 初始元空间大小
-XX:MaxMetaspaceSize 最大元空间大小
超过这个大小将会抛出OutOfmemoryError异常:java.lang.OutOfMemoryError: Metadata space
6.运行时常量池
运行时常量池是方法区的一部分。Class文件中除了有类的版本、字段、方法、接口等描述信息外,还有一项信息是常量池,用于存放编译期生成的各种字面量和符号引用,这部分内容将在类加载后进入方法区的运行时常量池中存放。
运行时常量池相对于Class文件常量池的另一个重要特征是具备动态性,java语言并不要求常量一定只有编译期才能产生,也就是并非预置入Class文件中常量池的内容才能进入方法区运行时常量池,运行期间也可能将新的常量放入池中。可以通过String.intern()方法强制放入常量池。
借鉴参考:《深入理解java虚拟机》
望大家共同进步!