JVM内存结构
Posted adeveloper
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JVM内存结构相关的知识,希望对你有一定的参考价值。
?
PS:蓝色块为线程独享空间
?
1、程序计数器(Program Counter Register)
1.1概述
a当前线程正在执行Java方法,记录所执行的虚拟机指令的地址。否则为空(Undefined)。
b每个线程都有独立的PC,
c字节码解释器工作时通过改变PC的值来选取下一条需要执行的字节码指令
d任意时刻JVM线程只会执行一个方法的代码(At any point, each Java Virtual Machine thread is executing the code of a single method)。
e这块的容量至少保存一个returnAddress类型的数据或一个与平台相关的本地指针的值(wide enough to hold a returnAddress or a native pointer on the specific platform)
f唯一一个在规范中没有规定任何OOM的区域
?
2、Java虚拟机栈(JVM Stack)
2.1概述
a每线程都有独立的虚拟机栈,生命周期和线程相同,可以在堆中分配
b分配的内存地址可以不需要保证连续
c每个方法执行时,都会同步创建个栈帧(Frame)
d栈的大小,可以固定,也可以配置动态收缩。
e栈的大小为固定时,线程可在创建时自定义栈大小
????new Thread(ThreadGroup group, Runnable target, String name, long stackSize)
f会抛出StackOverflowError和OutOfMemoryError
?
2.2栈帧(Frame)
2.2.1概述
a用于存储数据和部分过程结果的数据结构
b用于处理动态链接(Dynamic Linking),方法返回值(return values for methods)和异常分派(dispatch exceptions)
c生命周期同方法调用过程,且无论方法是否有异常,均视为结束,并销毁
(A frame is destroyed when its method invocation completes, whether that completion is normal or abrupt (it throws an uncaught exception))
d每个栈帧都有自己的一组局部变量表(Local Variable)、操作数栈(Operand Stack)、和指向当前方法所属类的运行时常量池的引用(a reference to the runtime constant pool of the class of the current method)
e栈帧数据结构大小仅取决于虚拟机的实现
d栈帧是线程私有数据
?
?
2.3局部变量表(Local Variable)
2.3.1概述
a长度由编译期决定,并通过方法的code属性(这里)保存以及提供给栈帧使用(supplied in the binary representation of a class or interface along with the code for the method associated with the frame)
b一个局部变量槽(Slot)可以保存一个类型为 boolean、byte、char、short、int、float、对象引用(reference)、 returnAddress的数据,long或者double需要两个连续的局部变量槽
c局部变量通过索引(indexing)来定位访问,索引从0开始
d一个局部变量槽的大小,由具体的虚拟机设计决定
e无论读写变量槽是否为原子操作,都不会引起数据竞争和线程安全问题。
f变量槽可以复用
?
2.4操作数栈(Operand Stack)
2.4.1概述
a后进先出(last-in-first-out, LIFO)
b栈深度在编译期决定,并通过方法的code属性保存以及提供给栈帧使用
c全称是:当前栈帧的操作数栈(Where it is clear by context, we will sometimes refer to the operand stack of the current frame as simply the operand stack.)
d在栈帧创建时,操作数栈是空的
e栈中元素的数据类型必须与字节码指令的序列严格匹配
f JVM的解释执行器引擎被称为"基于栈的执行引擎",这个栈就是,操作数栈
?
2.5动态链接(Dynamic Linking)
2.5.1概述
a通过一个指向当前方法所在类型的运行时常量池的引用,对当前方法的代码实现动态链接(Each frame contains a reference to the run-time constant pool for the type of the current method to support dynamic linking of the method code)
b类文件的常量池中存有大量的符号引用,字节码中的方法调用指令就是以常量池指向方法的符号引用作为参数
b.1静态解析:指一部分符号在类加载阶段或者第一次使用的时候就被转化为直接引用的转化
b.2动态链接:指一部分符号在每一次运行期间转化为直接引用的转化
?
2.6方法调用
2.6.1概述
a正常调用完成是指在方法执行过程中没有抛出任何异常,包括但不限于通过throw语句显式抛出的异常(A method invocation completes normally if that invocation does not cause an exception to be thrown, either directly from the Java Virtual Machine or as a result of executing an explicit throw statement)
b如果有返回值的话,使用哪种返回指令取决于方法返回值的数据类型
c异常调用完成是指方法在执行过程中抛出了异常,并且没有捕获异常
d方法异常调用完成,一定不会有方法返回值返回给调用者(A method invocation that completes abruptly never returns a value to its invoker)
e方法退出后都必须返回到最初方法被调用的位置,程序才能继续执行
f方法退出过程实际上等同于吧当前栈帧出栈
?
2.7 returnAddress数据类型
a用于jsr,ret,jsr_w 三种虚拟机指令
b值指向一个jvm操作指令,
cjava语言中没有对应的类型,且无法在运行中改变
d在旧的jvm中用于异常处理,现在用异常表代替
?
2.8 boolean数据类型
a JVM对boolean支持很有限,没有单独的操作指令
b对于java中boolean类型数据,会被编译成jvm中int数据类型(Instead, expressions in the Java programming language that operate on boolean values are compiled to use values of the Java Virtual Machine int data type)
c对于boolean数组,JVM复用byte数组的baload和bastore指令
d JVM用1表示true,0表示false
?
2.9 reference数据类型
a三种引用类型:类类型(class Types)、数组类型、接口类型
b默认值是null,但虚拟机没规定null值怎么表示(The default value of a reference type is null. This specification does not mandate a concrete value encoding null)
c没有规定reference的长度和结构,
d一般来说要做到下面两件事:
d.1可以直接或间接的查找到对象在堆中的数据存放的起始地址
d.2可以直接或间接的查找到对象所属数据类型在方法区中的存储的类型信息
e如果引用时数组类型,最外面那一维元素的类型,称为该数组的组件类型(component type)
An array type consists of a component type with a single dimension (whose length is not given by the type)
f元素类型(element type)定义太拗口,参考虚拟机规范jdk14的2.4章节
?
3、本地方法栈(Native Method Stack)
3.1概述
a为虚拟机用到的本地(Native)方法服务
b如果虚拟机不支持Native方法或不依赖传统栈(通常称C stack),可以没有本地方法栈
c会抛出StackOverflowError和OutOfMemoryError
e栈的大小,可以固定,也可以配置动态收缩。
f栈的大小为固定时,线程可在创建时自定义栈大小
e虚拟机栈和本地方法栈可以被设计为合二为一,比如HotSpot虚拟机。
?
4、堆(Heap)
4.1概述
a在虚拟机启动时创建,被所有线程共享
b可以划分出线程私有的线程缓冲区(Thread Local Allocation Buffer,TLAB)
c内存地址不需要保证连续,但在逻辑上应被视为连续的
d部分虚拟机设计,会针对大对象(比如数组)存储,要求内存地址是连续的
e容量可以固定,也可以动态扩展
f存储的对象无法显式销毁(objects are never explicitly deallocated)
g会抛出OutOfMemoryError
?
5、方法区(Method Area)
5.1概述
a别名非堆(Non-heap),不等价于永久代(Permanent Generation),被所有线程共享
b从JDK8开始,在本地内存中实现的元空间(Metaspace)代替永久代实现方法区
c存储了每个类的结构信息(It stores per-class structures),比如,运行时常量池(the run-time constant pool),字段和方法数据(field and method data),构造函数和普通方法的字节码内容(the code for methods and constructors),还包括一些在类、实例、接口初始化时用到的特殊方法(including the special methods used in class and instance initialization and interface initialization.)
d容量可以固定,也可以动态扩展,可以不实现GC
e会抛出OutOfMemoryError
f此区域的数据存储结构由JVM自定义,JVM规范不做具体规定
?
5.2运行时常量池(Run-Time Constant Pool)
a是class文件中每个类或接口的常量池表(constant_pool)的运行时表现形式(a per-class or per-interface run-time representation of the constant_pool table in a class file)
b包含编译期已知的数值字面量和运行期解析后获取的方法或字段引用(ranging from numeric literals known at compile-time to method and fi eld references that must be resolved at run-time)
ps:String.intern()
c会抛出OutOfMemoryError
d虚拟机规范没有对此作任何细节的要求
?
6、直接内存(Direct Memory)
6.1概述
a不是虚拟机运行时数据区的一部分,也不是《Java虚拟机规范》中定义的内存区域
b可能会抛出OutOfMemoryError
c可以通过DirectByteBuffer对象作为这块内存的引用进行操作
以上是关于JVM内存结构的主要内容,如果未能解决你的问题,请参考以下文章