转载

Java内存结构

根据《Java虚拟机规范(Java SE 8)》中描述了JVM运行时内存区域结构如图1所示: Java内存结构

图1 JVM运行时内存结构

图一即为JVM运行时的内存结构,下面我们对相关的结构进行分析。

1.1 PC寄存器-The PC Register

PC寄存器是内存中一块很小的区域,它的作用是作为行号指示器(一个指针:用来存储指向下一个指令的地址,即即将要执行的指令代码)指向方法区中的方法字节码,由执行引擎读(解释器—JVM组件)取下一条指令。分支、循环、异常处理、线程恢复等基础功能都需要依赖PC寄存器完成

特点:①线程私有;②没有内存溢出情况的产生。

1.2 Java虚拟机栈-Java Virtual Machine Stacks

图2是虚拟机栈Java线程执行方法的内存模型,一个线程对应一个栈(线程私有),因此栈的生命周期和线程的生命周期是同步的。当启动一个线程,程序调用函数,栈帧被压入栈中(先进后出,先进入的会被压入栈底),函数调用结束,相应的栈帧弹出栈。栈帧存储了方法的局部变量表、操作栈、动态连接和方法返回地址等相关信息,下面分别对他们进行简单的介绍。

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堆”。·

Java内存结构

图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所示),这部分内容将在类加载后进入方法区的运行时常量池中存放。 Java内存结构

图4 常量池组成

原文  http://4hou.win/wordpress/?p=46242
正文到此结束
Loading...