注:三大商用虚拟机:HotSpot、JRockit、IBM J9虚拟机,本文是针对HotSpot虚拟机而言的。
在理解类的记载机制之前,我们需要先理解Java内存相关的内容,主要从JVM内存结构,Java对象模型、Java内存模型三方面来了解。
一 JVM内存结构
根据《Java虚拟机规范(Java SE 8)》中描述了JVM运行时内存区域结构如图1所示:
图1 JVM运行时内存结构
图一即为JVM运行时的内存结构,下面我们对相关的结构进行分析。
1.1 PC寄存器-The PC Register
PC寄存器是内存中一块很小的区域,它的作用是作为行号指示器(一个指针:用来存储指向下一个指令的地址,即即将要执行的指令代码)指向方法区中的方法字节码,由执行引擎读(解释器—JVM组件)取下一条指令。分支、循环、异常处理、线程恢复等基础功能都需要依赖PC寄存器完成
特点:①线程私有;②没有内存溢出情况的产生。
1.2 Java虚拟机栈-Java Virtual Machine Stacks
图2是虚拟机栈Java线程执行方法的内存模型,一个线程对应一个栈(线程私有),因此栈的生命周期和线程的生命周期是同步的。当启动一个线程,程序调用函数,栈帧被压入栈中(先进后出,先进入的会被压入栈底),函数调用结束,相应的栈帧弹出栈。栈帧存储了方法的局部变量表、操作栈、动态连接和方法返回地址等相关信息,下面分别对他们进行简单的介绍。
图2 Java 方法执行的内存模型
局部变量表(Local Variable Table):局部变量表是用来存储一组变量值的内存空间,用于存放方法参数和方法内部定义的局部变量。其作用域是当前调用的函数,函数调用结束后,随着函数栈帧的销毁,局部变量表也会随之销毁,释放空间。
操作栈(Operand Stack):操作栈是一个后入先出(Last In First Out,LIFO)栈,用于存放调用过程中的计算结果的临时存放区域。
动态链接(Dynamic Linking):.class文件的常量池中存在有大量的符号引用,字节码中的方法调用指令就以指向常量池的引用作为参数,部分符号引用在运行期间转化为直接引用,这种转化为动态链接。
注:部分符号引用在类加载阶段(解析)的时候就转化为直接引用,这种转化为静态链接。
返回地址(Return Address):方法返回时可能需要在栈帧中保存一些信息,用来于恢复调用者(调用当前方法的方法)的执行状态(用于方法异常退出时,记录信息)。
1.3 本地方法栈-Native Method Stacks
本地方法栈与Java虚拟机栈类似,本地方法栈是本地方法运行的内存模型.本地方法被执行的时候,在本地方法栈也会创建一个栈帧,用于存放该本地方法的局部变量表、操作数栈、动态链接等相关信息。与Java虚拟机栈相比不同的是,本地方法栈服务的对象是JVM执行的native方法(用 Java 编程语言以外的语言编写的方法,执行也会创建栈帧),而虚拟机栈服务的是JVM执行的java方法。
1.4 Java堆-Heap
堆是JVM管理的最大的一块内存区域,存放着对象的实例,是线程共享区,由于数据共享,所以存在同步问题,需特别注意。
虚拟机启动时自动分配创建,几乎所有对象都在堆上分配内存,当对象无法在该空间申请到内存是将抛出OutOfMemoryError异常。
堆是垃圾收集器管理的主要区域,因此也被称为“GC堆”。·
图3 Heap组成结构
图3是Heap的组成结构图,Java堆分为年轻代(Young Generation)和老年代(Old Generation);年轻代又分为伊甸园(Eden Space)和幸存区(Survivor Space),所有的类都是在伊甸区被new出来的;幸存区又分为From Survivor空间和 To Survivor空间。
默认情况下,Heap中占比情况是:Young Generation:Old Generation=1:2;新生代Young Generation中占比情况是:Eden Space:From Survivor:To Survivor=8:1:1 。
注:①.垃圾回收机制会在以后的文章中介绍;②.以上占比均为JVM默认情况,其占比可改变。
1.5 方法区-Method Area
Method Area(方法区)是各个线程共享的内存区域方法区,又称Non-Heap(非堆),用于存储已被虚拟机加载的类信息、方法、常量、静态成员变量、JIT(即时编译器)编译后的代码等数据,在类加载时分配。
在JDK1.8之后,元空间(Meta Space)替代了永久代(Permanent Generation),它是对JVM规范中方法区的实现,区别在于元数据区不在虚拟机当中,而是用的本地内存,永久代在虚拟机当中,永久代逻辑结构上也属于堆,但是物理上不属于。
注:永久代和元空间可以看作方法区的一种实现,后面详解介绍永久代和元空间 。
1.6 运行时常量池-Run-Time Constant Pool
运行时常量池(Run-Time Constant Pool)是方法区的一部分,.Class文件中除了有类的版本、字段、方法、接口等描述信息外,还有一项信息是常量池(Constant Pool Table),用于存放编译期生成的各种字面量和符号引用(图4所示),这部分内容将在类加载后进入方法区的运行时常量池中存放。
图4 常量池组成
二 Java 对象模型
Java是一门面向对象的编程语言,在探究Java对象模型的时候,我们需要明白何为Java对象模型?简单的说Java对象模型就是Java对象在JVM虚拟机中的一种表现机制。
来源:freebuf.com 2020-07-04 19:06:01 by: codedogs
请登录后发表评论
注册