读《深入Java虚拟机》的时候,第一章就是描述JVM在内存上的结构模型,特此记录整理。(图暂时借一下YSOcean的,稍后用自己画的替换)。
4. JVM运行时内存结构(内存结构模型)
java虚拟机规范定义的运行时数据区:
最大的的一块是堆,属于线程公有的区域,用来存放对象实例。
栈分为本地方法栈,以及虚拟机栈,是线程私有的,分别用于调用native方法和java方法。每次调用方法的时候,栈顶会创建一个栈帧,存放局部变量表、操作数栈、动态链接、方法返回地址。
程序计数器用来存储当前执行的指令地址,是线程私有的。(唯一一个不会抛OOM的区域)
方法区,线程共享区域,存放类的结构信息、常量、静态变量、运行时常量池(存放编译期产生的字面量和符号引用)。
Hotspot JDK1.8的运行时数据区:
①、将Java虚拟机栈和本地方法栈合二为一;
②、元数据区取代了方法区,并且元数据区不在Java虚拟机中,而是在本地内存中。
③、运行时常量池由方法区中移到了堆中
栈
StackOverflow和OutOfMemory的区别??
Java堆
- 线程共享,存放对象实例和数组(随着JIT的发展和逃逸分析技术的成熟,有的对象会分配在栈上);
- 垃圾收集:java堆可以进一步分为新生代和老年代,而新生代又可以分为Eden空间、From Survivor空间、To survivor空间,主要是因为新生代使用的是复制算法。
- 根据Java虚拟机规范,Java堆可以处于物理上不连续的内存空间中, 只要逻辑上连续即可,实现时既可以实现成固定大小,也可以是扩展的。如果堆中没有完成实例分配,并且无法扩展,将抛出OOM异常。
方法区
存储已经被JVM加载的类的信息、常量、静态变量、即时编译器编译后的代码等数据。运行时常量池用来存放编译期生成的各种字面量和符号引用。方法区也成为永久代,因为垃圾回收期对方法区的垃圾回收较少,主要是针对常量池的回收、对类型的卸载,回售条件比较苛刻,经常会导致内存泄漏,当方法区无法满足内存分配时抛出OOM异常。