JVM_JVM的内存区域划分

     

     总所周知,JVM 是 Java 的一个核心概念。从今天开始,我们对这块进行一个归纳整理。

 

JVM 运行时,主要包括以下几个运行时的数据区域。

 

其中: 

方法区 与 堆 是所有线程共享的数据区

虚拟机栈,本地方法栈,程序计数器 是线程隔离的

 

 

程序计数器

   程序计数器 (Program Counter Register)是一块较小的内存空间,它可以看作是当前线程执行的字节码的行号指示器。

   在虚拟机的概念模型里,字节码解释器工作时通过改变这个计数器的值来选取下一跳需要执行的字节码指令,分支,循环,跳转,异常处理,线程回复等基础功能需要该计数器完成

 

Java 虚拟机栈

   Java 虚拟机栈 (Java Virtual Machine Stacks)是线程私有的,他的生命周期与线程相同。虚拟机栈描述的是Java 方法执行的内存模型:每个方法在执行的同时,都会创建一个帧栈(Stack Frame)用于储存局部变量表,操作数栈,动态链接,方法出口信息等信息。

   每一个方法从调用直至执行完成的过程,就对应着一个帧栈在虚拟机中入栈到出栈的过程。

 

本地方法区

    本地方法栈(Native Method Stack)与虚拟机栈的作用非常相似,他们之前的区别不过是   虚拟机栈为虚拟机执行Java 方法(字节码)服务,而本地方法栈则为虚拟机使用到的Native 方法服务。

 

Java堆

    Java堆 (Java Heap)是Java 虚拟机所管理的内存中最大的一块。Java 堆是被所有线程共享的一块内存区域,在虚拟机启动时创建。此内存区域的唯一目的就是存放对象实例,几乎所有的对象实例都在这里分配内存。

现代的垃圾回收器都采用分代手机算法,Java堆还细分为 新生代 / 老年代 ,

再细致一点的有 Eden, From Survivor, To Survivor 空间。从内存分配的角度来说,线程共享的Java 堆中可能划分出多个线程私有的分配缓冲区(Thread Local Allocation Buffer , TLAB).

 

方法区

 

  总体

   方法区 (Method Area)与 Java 堆一样,是各个线程共享的内存区域,它用于存储已经被虚拟机加载的类信息,常量,静态变量,即时编译器 变异后的代码 等数据。

   虽然 Java 虚拟机规范把方法去描述为堆的一个逻辑部分,但是它却有一个别名叫做 Non-Heap(非堆) , 目前与 Java堆 分开 (Java 8 +)

   对于习惯在 HotSpot 虚拟机上开发,部署程序的开发者来说,很多人都更愿意把方法区称为 永久代(Permanent Generation), 本质上两者不等价,仅仅是因为 HotSpot 虚拟机的设计团队选择把GC分代扩展至方法区,或者说用永久代来实现方法区而已。 HotSpot 垃圾收集器可以像管理Java 堆一样去管理这部分内存。

 

  永久代实现方法区,现在看来并不是一个好主意,因为这样更容易遇到内存溢出的问题(永久代 有 -XX:MaxPermSize 的上限)。对于HotSpot 虚拟机,根据官方发布的路线图信息,现在也有放弃 永久代,并逐步改为采用 Native Memory 来实现方法区的规划。

    在Jdk 1.7 中,已经把原本放在永久代的 字符串常量池 移出。

  

  运行时常量池

     运行时常量池 (Runtime  Constant Pool )是方法区的一部分。Class 文件中除了有类的版本,字段,方法,接口等描述信息外,还有一项是常量池 (Constant Pool table ), 用于存放编译器生成的各种字面量 和 符号引用。这部分内容将在类加载后进入方法区的运行时常量池中存放。

   Java 语言并不要求 常量一定只有编译期才能产生,也就是非预置入Class 文件中常量池的内容才能进入方法区常量池,运行期间也可能将新的变量放入池中。

 

 

直接内存

    直接内存(Direct Memory )并不是虚拟机运行时数据区的一部分,也不是 Java 虚拟机规范中定义的内存区域。但是这部分吗内存也被频繁地使用,而且也可能导致 OutOfMemoryError 异常出现,所以我们放到这里一起讲解。

   JDK 1.4 中新加入了 NIO (New Input / Output) 类, 引入了一种基于通道 (Channel)与缓冲区 (Buffer ) 的 I/O 方式,他可以使用  Native 函数库直接分配堆外内存,然后通过一个存储在 Java 堆中的 DirectByteBufffer 对象作为这块内存的引用进行操作。这样在一些场景中显著提高性能,因为避免了在 Java 堆中 和 Native 堆中来回复制数据。

 

 

 

    

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值