`
ssydxa219
  • 浏览: 608785 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
文章分类
社区版块
存档分类
最新评论

初识 JVM 内存区域划分

 
阅读更多

 

大多数 JVM 将内存区域划分为   Method Area Non-Heap Heap Program Counter Register Java Method Stack , Native Method Stack     Direct Memomry (注意 Directory Memory 并不属于 JVM 管理的内存区域)。前三者一般译为:方法区、堆、程序计数器。但不同的资料和书籍上对于后三者的中文译名不尽相同,这里将它们分别译作: Java 方法栈、原生方法栈和直接内存区。对于不同的 JVM ,内存区域划分可能会有所差异,比如 Hot Spot 就将 Java 方法栈和原生方法栈合二为一,我们可以同城为方法栈( Method Stack )。

 

首先我们熟悉一下一个一般性的 Java 程序的工作过程。一个 Java 源程序文件,会被编译为字节码文件(以 class 为扩展名),然后告知 JVM 程序的运行入口,再被 JVM 通过字节码解释器加载运行。那么程序开始运行后,都是如何涉及到各内存区域的呢?

 

概括地说来, JVM 每遇到一个线程,就为其分配一个程序计数器、 Java 方法栈和原生方法栈。当线程终止时,两者所占用的内存空间也会被释放掉。栈中存储的是栈帧,可以说每个栈帧对应一个 运行现场 。在每个 运行现场 中,如果出现了一个局部对象,则它的实例数据被保存在堆中,而类数据被保存在方法区。

 

我们用上面这一小段文字就描述完了每个内存区域的基本功能。但是这还比较粗糙,下面分别介绍它们的存储对象、生存期与空间管理策略。

 

2.1 程序计数器

 

线程特性:私有

 

存储内容:字节码文件指令地址( Java Methods ),或 Undefined Native Methods

 

生命周期:随线程而生死

 

空间策略:占用内存很小

 

这个最简单,就先捡它说吧。程序计数器,是线程私有(与线程共享相对)的,也就是说有 N 个线程, JVM 就会分配 N 个程序计数器。如果当前线程在执行一个 Java 方法,则程序计数器记录着该线程所执行的字节码文件中的指令地址。如果线程执行的是一个 Native 方法,则计数器值为 Undefined

 

程序计数器的生存期多长呢?显然程序计数器是伴随线程生而生,伴随线程死而死的。而它所占用的内存空间也很小。

 

2.2 Java 方法栈与原生方法栈

 

Java 方法栈也是线程私有的,每个 Java 方法栈都是由一个个栈帧组成的,每个栈帧是一个方法运行期的基础数据结构,它存储着局部变量表、操作数栈、动态链接、方法出口等信息。当线程调用调用了一个 Java 方法时,一个栈帧就被压入( push )到相应的 Java 方法栈。当线程从一个 Java 方法返回时,相应的 Java 方法栈就弹出( pop )一个栈帧。

 

其中要详细介绍的是局部变量表,它保存者各种基本数据类型和对象引用( Object reference )。基本数据类型包括 boolean byte char short int long float double 。对象引用,本质就是一个地址(也可以说是一个 指针 ),该地址是堆中的一个地址,通过这个地址可以找到相应的 Object (注意是 找到 ,原因会在下面解释)。而这个地址找到相应 Object 的方式有两种。一种是该地址存储着 Pointer to Object Instance Data Pointer to Object Class Data ,另一种是该地址存储着 Object Instance Data ,其中又包含有 Pointer to Object Class Data

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics