java架构师必备技能-JVM内存模型详解

鲁班学院 java架构师必备技能-JVM内存模型详解

一、JVM包含哪几个部分

java架构师必备技能-JVM内存模型详解

1、类加载器(Class Loader):加载类文件到内存。Class loader只管加载,只要符合文件结构就加载,至于能否运行,它不负责,那是由Exectution Engine 负责的。

2、执行引擎(Execution Engine):也叫解释器,负责解释命令,交由操作系统执行。

3、本地库接口(Native Interface):本地接口的作用是融合不同的语言为java所用。

4、接下来详细讲解运行时数据区。

二、

java架构师必备技能-JVM内存模型详解

上图是JVM概念模型(仅仅是概念模型,不同的java虚拟机有不同的实现),大多博客讲解忽略了这一点,导致读者概念混乱。

2.1 程序计数器

(1)字节码解释器通过改变程序计数器的值来选取下一条需要执行的字节码指令,分支、循环、跳转、异常处理、线程恢复等基础功能都依赖这个计数器完成。

(2)每条线程都有一个独立的程序计数器。

(3)如果执行的是Java方法,这个计数器记录的就是正在执行的字节码指令地址;如果是native方法,则计数器的值为Undefined。这也是JVM规范中唯一一个没有规定OutOfMemoryError的区域。

2.2 Java虚拟机栈

(1)Java虚拟机栈也是线程私有的。Java虚拟机栈描述的是Java方法执行的内存模型:每个方法执行的时候都会创建一个栈帧,用于存储局部变量表、操作数栈、动态链接、方法出口等信息。每一个方法从调用到执行完成的过程,就对应这栈帧入栈到出栈的过程。

java架构师必备技能-JVM内存模型详解

(2)常说的堆栈,这里的栈指的就是栈帧或者说是栈帧中的局部变量表部分。其中局部变量表存放了编译期可知的各种基本数据类型、对象引用和returnAddress类型(一条字节码指令地址)。long和double占用2个局部变量空间(Slot),其余数据类型占用1。

(3)该区域规定了两种异常情况。StackOverflow(线程请求的栈深度大于虚拟机所允许的深度)和OutOfMemoryError(无法申请到足够的内存)。

2.3 本地方法栈

本地方法栈与Java虚拟机栈类似,虚拟机栈为虚拟机执行Java方法(字节码)服务,而本地方法栈为Native方法服务。HotSpot将本地方法栈和虚拟机栈合二为一。

例如Unsafe类下用native修饰的方法,其底层由C或C++实现,Java进行调用。

java架构师必备技能-JVM内存模型详解

2.4 堆

(1)绝大部分对象实例在堆上分配,但并不绝对。

(2)如果采用基于分代收集算法的垃圾收集器(一定是基于分代收集算法!),Java堆还可以细分为新生代和老年代;再细致可分为Eden区、From Survivor区、To Survivor区,关于分代收集,会在后面详细讲解。

(3)堆无法扩展时,将会抛出OutOfMemoryError。

2.5 方法区

(1)用于存储类信息、常量、静态变量、即时编译器编译后的代码。、

(2)方法区在HotSpot虚拟机(Oracle Jdk和OpenJdk带的虚拟机)用永久代(个人理解方法区+GC分代收集=永久代)实现的,HotSpot将GC分代收集扩展到方法区(本来只在堆中),这样HotSpot就可以像管理Java堆一样管理这部分内存。(对于如BEA Jrockit、IBM J9是不存在永久代的概念)。在JDK7中,官方已经把原本存在永久代的字符串常量池从永久代中移出(目前大部分博客认为被移动到了堆区,尚未验证)。JDK8中废弃了永久代的概念,改用元空间。

(3)该区域会抛出OutOfMemoryError。

2.6 运行时常量池

(1)运行时常量池是方法区的一部分。用于存放Class文件的常量池(Constant Pool Table,用于存放编译期生成的各种字面量和符号引用),这部分内容将在类加载后进入方法区的运行时常量池存放。

通过执行javap -verbose xxxx.class命令可以查看到class文件信息,下图是常量池信息

java架构师必备技能-JVM内存模型详解

猜你喜欢

转载自blog.51cto.com/14993817/2547642