JVM的垃圾收集机制和内存分配策略

首先给大家看一下JVM的数据区模型。


上图是JVM的数据区模型。但是在Hotspot JVM中,我们知道运行时常量是属于方法区的,而方法区又属于堆。对于栈,在hotspot中虚拟机栈和本地栈是合二为一的。

这里在顺便说一说虚拟机对象的结构,如下图所示


这里在提一提对象的引用问题:

Java是按值传递的,Java不存在引用传递。所谓的栈上的引用是用来操作堆上的具体的对象。但是这些引用实际上是这些具体对象在堆上的绝对地址的值。


接下来说说垃圾回收机制。通常我们所说的垃圾回收主要是针对堆的空间的。我们知道Java中的对象和数组的创建都是在堆上完成的。当存在不需要的对象或者当有对象游离时(object=null)时,或者JVM的内存资源紧张时,JVM都会考虑进行垃圾回收。

堆的分配是按对象存活的时间分为新生代和老年代。具体如下图所示:


堆内存是这样分配的,有新生代和老年代之分。新生代又分为Eden区、To survivor区和From surivivor区。它们的比例的大小是811。在新生代中Eden区和To survivor区负责存储new出来的对象。当存储的对象过多时,JVM会进行垃圾回收。垃圾回收的机制是一种叫可达性的算法。在确定了要清理的对象后,接下来主要分为两部分:标记-清理、和停止复制。JVM首先会在Eden区和To survivor区进行标记-清理动作。这将会清理掉部分的垃圾。对于那些存活的对象,会被复制到From survivor区域中。

如果当Eden区和两个survivor区都块用完的时候,这时候在进行可达性算法的垃圾回收时,我们会将存活时间较长的对象复制到老年代中进行存储。至于存活时间的阈值我们可以在通过虚拟机参数 -XX:MaxTenuringThreshold来设置的。这有点像担保机制一样,老子为儿子的借款做担保。如果儿子无力偿还就由老子来还。(这就是内存的担保机制)

当然了,对于哪些较大的对象。而且生命周期很长的对象。我们是直接将他们存储在老年代中。在老年代中,进行垃圾回收的时候也是使用可达性算法的。在确定了要清理的对象后,就开始进行标记-清除,但这样会出现许多内存碎片,于是接下来的动作就是复制。


最后来说说JVM的垃圾回收器。一共有7种垃圾回收器。如下图所示:


Serial:单线程的,回收新生代的垃圾回收器。它是虚拟机运行在Client模式下的默认新生代垃圾回收器。

Serial old:Serial是对应的,主要回收老年代的垃圾。

ParNew:主要就是Serial的多线程版。

Parallel新生代收集器,:它是并发的多线程收集器,主要使用的是复制的算法。它主要是受一个可控制的吞吐量的影响。所谓的吞吐量就是CPU运行用户代码的时间和CPU的总的消耗时间的比值。

Parallel Old:Parallel相对应,主要回收老年代的垃圾。

CMS:是一种以获取最短的回收停顿时间为目标的收集器。目前主要用于大部分的Java应用集中在互联网站和B/S系统服务中。

G1:是一个面向服务器端应用的垃圾收集器。它是即可回收新生代也可以回收老年代。



猜你喜欢

转载自blog.csdn.net/LULEI1217/article/details/50954300