java虚拟机内存模型

最近在看java虚拟机相关的书,从网上找了个图,认为可以大致描述出java虚拟机的部分。

java虚拟机内存模型

———————————–各线程私有区————————–

程序计数器 PC:

1.每个线程都会有自己的程序计数器,也就是线程私有。
2.如果程序执行的是java代码,则计数器记录执行的字节码的指令地址。如果执行native(native是啥,自己查)代码,则不记录。
3.javap -c classname 可以看到字节码的地址
4.线程切换、恢复时都依赖PC中的值。
5.因为此区域占用内存空间较小,所以没有OutOfMemoryError的情况。


虚拟机栈(VM Stack):

1.线程私有,生命周期和线程相同。
2.栈帧包括,局部变量表、 操作数栈、 动态链接、 方法出口等信息,总之,是用于方法调用和方法执行的数据结构。
3.栈帧可以理解为一个方法的运行空间,每个方法被执行时,会创建一个栈帧。
4.方法从执行开始到结束,都对应一个栈帧在虚拟机中从入栈到出栈的过程。
5.线程请求的栈深度如果超过虚拟机允许的最大深度,则抛出 *Error 异常。


本地方法栈:
作用是支持native方法的调用与返回。

———————————–各线程共享区————————–
方法区:

  1. 方法区是各线程共享的区域,所以必须设计成线程安全的。
  2. 存储了每个类的结构信息,如运行时常量池,字段、方法、数据等。
  3. 方法区的大小决定了系统可以包含多少个类,如果系统类太多,虚拟机同样会抛出内存溢出信息。
  4. 虚拟机启动时创建。
  5. 有时,永久代(PerGen Space)就指的是方法区。
  6. -XX:PermSize 方法区初始大小 -XX:MaxPermSize 方法区最大值,超出则报错 OutOfMemoryError。
  7. 在jdk1.8,已经将永久代移除了,以元空间来取代。用-XX:MetaspaceSize 和 •-XX:MaxMetaspaceSize 来调节大小。
  8. 方法区中有个静态区,专门存储静态变量以及静态块。

常量池:
1.String str = “abc”,常量池中将存储abc对象。
2.String str1 = new String(“abc”); 常量池和堆中都将有abc对象,并且他们之间会建立联系。
3.对于equals相等的字符串,在常量池中永远只存储一份。
4.intern(),方法返回在堆中的对象在常量池中的对应的对象的引用,即str==str1.itern()会返回true.


堆:heap

1.堆是所有线程共享的内存区域,是虚拟机所管理的内存最大的一块,在虚拟机启动时创建。
2.所有对象实例都在这里分配内存。
3.堆是垃圾收集器管理的主要区域,所以又叫GC堆。
4.内存回收大多按照分代收集的算法,堆一般分为新生代和老年代。新生代又可分为Eden,form,to空间。
5.如果堆中没有空间可以继续分配对象实例,并且也无法扩展时,将抛出OutOfMemoryError异常。
6.大小可以通过-Xmx和-Xms控制。