您的位置:首页 > 编程语言 > Java开发

理解Java虚拟机

2016-03-23 15:03 459 查看

一、简介

Java运行时,会将管理的内存划分成各个不同区域,每个区域的功能以及生命周期都不同。下面将大致介绍各个内存区域的作用。



二、具体区域

program counter register(程序计数器)

可以看作是是当前线程所执行的字节码的行号指示器。字节码解释器工作时就是通过改变这个计数器的值进行跳转。显而易见的是程序计数器是线程私有的。

如果线程正在执行的是一个Java方法,计数器记录的则是正在执行的虚拟机字节码指令的地址;如果正在执行的是Native方法,则计数器值为空。此内存区域没有规定任何OOM情况。

JAVA STACK (Java虚拟机栈)

虚拟机栈,线程私有,生命周期和线程相同,每个方法都会创建一个栈桢用于存储局部变量表、操作数栈、动态链接、方法出口等信息。每个方法都对应着一个栈桢入栈和出栈。

如果线程请求的栈深度大于虚拟机允许的深度就会抛出stackOverFlowError。

(NATIVE METHOD STACK)本地方法栈

本地方法栈可以使用虚拟机的Native方法,其他的和虚拟机栈类似。

Java堆

Java堆是被所有线程共享的一块内存区域,在虚拟机启动时创建,此内存区域唯一目的是存放对象实例,所有的对象实例及数组都要在堆上分配。Java堆中也分为新生代和老年代。以及更加细致的划分。

方法区

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

对于HotSpot虚拟机,方法区也成为(Permanent Generation)永久代,这里面的垃圾回收很少发生。

TIPS:在实际开发中,如果装载的类库过多,就可能导致方法区溢出,可以通过修改虚拟机方法区大小改变

运行时常量池

它是方法区一部分,用于存放编译器生成的各种字面量和符号引用,比如String字符串常量池。

直接内存

这部分内存并不是运行时数据区的一部分,而是NI/O中,引入了基于channel和buffer的I/O方式,它可以使用Native函数库直接分配堆外内存,通过一个存储在Java堆中的DirectByteBuffer对象作为这块内存的引用进行操作。

三、堆内存分区

在jdk1.7之前,堆内存主要分为老年代和新生代这两个区域。顾名思义,老年代是指在堆中存活很久的对象,新生代是指存活较短的对象。新生代和老年代的比例一般是1:2。同时,新生代又分为Eden,FromSurvivor,To Survivor区域。因为这里主要使用的是标记复制算法,可以避免内存碎片。虚拟机将新生代分为一个较大的Eden和两个较小的suvivor,默认为比例是8:1:1,也可以通过指定参数SurvivorRatio来调整。在分配的时候会首先分配到Eden和其中一个survivor区域上。在回收的时候会把存活的对象转移到另一块survivor上,如果另一块区域也存放不下,就会转移到老年代中。

既然对堆内存分区,肯定针对每个区有不同的GC策略。

1.Minor GC:发生在新生代的垃圾回收,速度很快,频率很高。

2.Major GC/Full GC:发生在老年代的GC,出现了一般使用标记-清楚或者标记-整理算法。

按照正常流程,新生代中的对象每经历一次Minor GC并且存活下来,年龄就会增加一次,当增加到(默认)15岁,就会直接晋升到老年代。

如果主动调用System.gc()会触发Minor GC和Full GC,同时会让新生代提前进入老年代。

四、垃圾回收器种类

垃圾收集器是gc回收的具体实现。

新生代垃圾回收:

Serial

单线程收集器,历史悠久,依然是一些client端新生代默认的收集器,存在一些GC停顿

ParNew

Serial的多线程版本,能多线程收集,但是不能和后面的CMS收集器相比,CMS可以完全做到边收集边让工作线程工作。

Parallel Scavenge

和上述收集器不同点在于Paralle Scavenge收集器目标是达到一个可控制的吞吐量(CPU用于运行用户代码的时间与CPU总消耗时间的比值),此收集器可以通过-XX:MaxGCPauseMillis和 -XX:GCTimeRatio参数来设置吞吐量相关参数

老年代垃圾回收

Serial Old

是Serial的老年代版本,采用了标记-整理算法

Parallel Old

Parallel old 是 Parallel Scavenge 的老年代版本,使用了多线程和标记-整理算法。由于在服务端有多CPU处理能力,所以尽量使用并行收集,在注重吞吐量或者CPU资源敏感的场合,可以考虑Paralle Scanvenge加Parallel Old收集器。

CMS收集器

CMS是为了获取最短停顿时间为目标的收集器,应用在B/S系统的服务端上。收集分四个步骤:

初始标记(mark)

并发标记(concurrent mark)

重新标记(remark)

并发清除(concurrent sweep)

在1.3两个步骤依然需要“stop the world”。初始标记主要标记GC Roots能关联到的对象,速度快。

并发标记是GC Tracing的过程,重新标记是为了修正并发标记期间因用户程序继续运作二导致标记变动的对象标记记录,由于整个过程最耗时的并发标记和并发清除过程是与用户线程一起并发执行,所以能节约时间。

G1收集器

1.并行与并发:能利用多CPU和多核

2.分代收集:

3.空间整合:利用标记-整理算法,能有效降低内存碎片,减少FULL GC

4.可预测停顿:G1建立了可预测的停顿时间模型,能让使用者明确指定在一个长度为M毫秒的时间片段内,消耗在垃圾收集上的时间不得超过N秒。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: