本篇是对 JVM 基本概念的回顾,主要参考了《深入理解 Java 虚拟机》。
内存模型
- 线程隔离的数据区:
- 程序计数器,指示当前线程所执行的字节码行号
- 虚拟机栈,生命周期与线程相同,存储局部变量表(编译时可预知的基本数据类型,对象引用,returnAddress)。描述的是 Java 方法执行的模型:每个方法执行是都会创建一个栈帧用来存储局部变量表,方法出口,操作数栈,动态链接等,方法开始时入栈,结束时出栈
- 本地方法栈,与虚拟机栈类似,只不过执行的是 Native 方法
- 线程共享的数据区:
- 堆,存放对象实例
- 方法区,存储虚拟机加载的类信息,常量,静态变量,及时编译后的代码等。包含运行时常量池
- 不属于 JVM 管理的内存区域
- 直接内存:在 JDK1.4 中新加入了 NIO(New Input/Output)类,引入了一种基于通道(Channel)与缓冲区(Buffer)的 I/O 方式,它可以使用 native 函数库直接分配堆外内存,然后通过一个存储在 Java 堆中的 DirectByteBuffer 对象作为这块内存的引用进行操作。这样能在一些场景中显著提高性能,因为避免了在 Java 堆和 Native 堆中来回复制数据。
JDK8 中 JVM 发生的变化
元数据区取代了永久代。元空间的本质和永久代类似,都是对 JVM 规范中方法区的实现。不过元空间与永久代之间最大的区别在于:元数据空间并不在虚拟机中,而是使用本地内存。
原因:
- 官方文档:移除永久代是为融合 HotSpot JVM 与 JRockit VM 而做出的努力,因为 JRockit 没有永久代,不需要配置永久代
- PermGen 很难调整,PermGen 中类的元数据信息在每次 FullGC 的时候可能被收集,但成绩很难令人满意。