声明
JVM:HotSpot;JDK版本:1.7 和 1.8
根据《Java 虚拟机规范》规定,Java虚拟机所管理的内存将由堆、虚拟机栈、本地方法栈、方法区和程序计数器5部分构成。
1.堆:
- 绝大部分对象的核心存储区域,但是也不是绝对的。
- 从内存回收的角度看,由于现在垃圾收集器基本都采用分代收集算法,所以Java堆还可细分为新生代和老年代;新生代又可以分为 Eden 空间和 Survivor 空间,Survivor 又由 From Survivor 和 To Survivor 空间组成,具体划分情况如下图:
- 被所有 Java 线程所共享,所以在访问时需要注意同步问题。
2.虚拟机栈:
- 每创建一个线程 JVM 就会创造出一个对应的线程栈。
- 每个方法创建同时会创建出一个栈帧,用于存储方法局部变量、操作数、动态链接、方法出口等。
- 线程私有。
3.本地方法栈:
- 与虚拟机栈作用相同,区别只在于本地方法栈用来执行本地方法。有的虚拟机比如:HotSpot 在实现时直接将本地方法栈和虚拟机栈合二为一。
4.方法区:
- 存储已经被虚拟机加载的类结构信息:常量、静态变量、即使编译器编译之后的代码等数据。
- 方法区有一个别名:Non-Heap,目的是与堆区分开来。
- 方法区常被称为永久代,但是这种说法并不完全正确,永久代只是方法区的一种实现方式,对于其他的虚拟机,如 JRockit、IBM J9等并不存在永久代的概念。对于 Hotspot 官方也放弃了永久代,在 JDK 1.7中将字符串常量池移到本地内存中,而到了 JDK1.8 中已经将永久代移除,使用元空间来代替。
- 方法区是线程共享的。
5.程序计数器:
- 记录当前线程的内存地址。
- 如果执行的是 native 方法,则为 Undefined。
- 程序计数器是线程私有的。
[参考]
- 《Java 虚拟机规范 1.7》
- 《Java 虚拟机规范 1.8》
- 《深入理解 Java 虚拟机》