jvm内存模型,
分享于 点击 44393 次 点评:64
jvm内存模型,
http://www.cnblogs.com/dingyingsi/p/3760447.html4、Java 堆
对于大多数应用来说,Java 堆(Java Heap)是Java 虚拟机所管理的内存中最大的
一块。Java 堆是被所有线程共享的一块内存区域,在虚拟机启动时创建。此内存区域的
唯一目的就是存放对象实例,几乎所有的对象实例都在这里分配内存。这一点在Java 虚
拟机规范中的描述是:所有的对象实例以及数组都要在堆上分配①,但是随着JIT 编译器
的发展与逃逸分析技术的逐渐成熟,栈上分配、标量替换②优化技术将会导致一些微妙
的变化发生,所有的对象都分配在堆上也渐渐变得不是那么“绝对”了。
Java 堆是垃圾收集器管理的主要区域,因此很多时候也被称做“GC 堆”(Garbage
Collected Heap,幸好国内没翻译成“垃圾堆”)。如果从内存回收的角度看,由于现在
收集器基本都是采用的分代收集算法,所以Java 堆中还可以细分为:新生代和老年代;
再细致一点的有Eden 空间、From Survivor 空间、To Survivor 空间等。如果从内存分配
的角度看,线程共享的Java 堆中可能划分出多个线程私有的分配缓冲区(Thread Local
Allocation Buffer,TLAB)。不过,无论如何划分,都与存放内容无关,无论哪个区域,
存储的都仍然是对象实例,进一步划分的目的是为了更好地回收内存,或者更快地分配
内存。在本章中,我们仅仅针对内存区域的作用进行讨论,Java 堆中的上述各个区域的
分配和回收等细节将会是下一章的主题。
根据Java 虚拟机规范的规定,Java 堆可以处于物理上不连续的内存空间中,只要
逻辑上是连续的即可,就像我们的磁盘空间一样。在实现时,既可以实现成固定大小
的,也可以是可扩展的,不过当前主流的虚拟机都是按照可扩展来实现的(通过-Xmx
和-Xms 控制)。如果在堆中没有内存完成实例分配,并且堆也无法再扩展时,将会抛出
OutOfMemoryError 异常。
4、方法区
方法区(Method Area)与Java 堆一样,是各个线程共享的内存区域,它用于存
储已被虚拟机加载的类信息、常量、静态变量、即时编译器编译后的代码等数据。虽
然Java 虚拟机规范把方法区描述为堆的一个逻辑部分,但是它却有一个别名叫做Non-
Heap(非堆),目的应该是与Java 堆区分开来。
对于习惯在HotSpot 虚拟机上开发和部署程序的开发者来说,很多人愿意把方法区
称为“永久代”(Permanent Generation),本质上两者并不等价,仅仅是因为HotSpot 虚
拟机的设计团队选择把GC 分代收集扩展至方法区,或者说使用永久代来实现方法区而
已。对于其他虚拟机(如BEA JRockit、IBM J9 等)来说是不存在永久代的概念的。即
使是HotSpot 虚拟机本身,根据官方发布的路线图信息,现在也有放弃永久代并“搬家”
至Native Memory 来实现方法区的规划了。
Java 虚拟机规范对这个区域的限制非常宽松,除了和Java 堆一样不需要连续的内
存和可以选择固定大小或者可扩展外,还可以选择不实现垃圾收集。相对而言,垃圾
收集行为在这个区域是比较少出现的,但并非数据进入了方法区就如永久代的名字一
样“永久”存在了。这个区域的内存回收目标主要是针对常量池的回收和对类型的卸
载,一般来说这个区域的回收“成绩”比较难以令人满意,尤其是类型的卸载,条件
相当苛刻,但是这部分区域的回收确实是有必要的。在Sun 公司的BUG 列表中,曾出
现过的若干个严重的BUG 就是由于低版本的HotSpot 虚拟机对此区域未完全回收而导
致内存泄漏。
根据Java 虚拟机规范的规定,当方法区无法满足内存分配需求时,将抛出
OutOfMemoryError 异常。
相关文章
- 暂无相关文章
用户点评