JVM内存管理及垃圾回收详解(3)

b> 软引用(Soft Reference).声明为软引用的类,是可被回收的对象,如果JVM内存并不紧张,这类对象可以不被���收,如果内存紧张,则会被回收。此处有一个问题,既然被引用为软引用的对象可以回收,为什么不去回收呢?其实我们知道,Java中是存在缓存机制的,就拿字面量缓存来说,有些时候,缓存的对象就是当前可有可无的,只是留在内存中如果还有需要,则不需要重新分配内存即可使用,因此,这些对象即可被引用为软引用,方便使用,提高程序性能。

c> 弱引用(Weak Reference).弱引用的对象就是一定需要进行垃圾回收的,不管内存是否紧张,当进行GC时,标记为弱引用的对象一定会被清理回收。

d> 虚引用(Phantom Reference).虚引用弱的可以忽略不计,JVM完全不会在乎虚引用,其唯一作用就是做一些跟踪记录,辅助finalize函数的使用。

最后总结,什么样的类需要回收呢?无用的类,何为无用的类?需满足如下要求:

1> 该类的所有实例对象都已经被回收。

2> 加载该类的ClassLoader已经被回收。

3> 该类对应的反射类java.lang.Class对象没有被任何地方引用。

4、如何进行垃圾回收?

本块内容以介绍垃圾回收算法为主,因为我们前面有介绍,内存主要被分为三块,新生代、旧生代、持久代。三代的特点不同,造就了他们所用的GC算法不同,新生代适合那些生命周期较短,频繁创建及销毁的对象,旧生代适合生命周期相对较长的对象,持久代在Sun HotSpot中就是指方法区(有些JVM中根本就没有持久代这中说法)。首先介绍下新生代、旧生代、持久代的概念及特点:

JVM内存管理及垃圾回收详解

新生代:New Generation或者Young Generation。上面大致分为Eden区和Survivor区,Survivor区又分为大小相同的两部分:FromSpace 和ToSpace。新建的对象都是用新生代分配内存,Eden空间不足的时候,会把存活的对象转移到Survivor中,新生代的大小可以由-Xmn来控制,也可以用-XX:SurvivorRatio来控制Eden和Survivor的比例.
旧生代:Old Generation。用于存放新生代中经过多次垃圾回收仍然存活的对象,例如缓存对象。旧生代占用大小为-Xmx值减去-Xmn对应的值。

持久代:Permanent Generation。在Sun的JVM中就是方法区的意思,尽管有些JVM大多没有这一代。主要存放常量及类的一些信息默认最小值为16MB,最大值为64MB,可通过-XX:PermSize及-XX:MaxPermSize来设置最小值和最大值。

常见的GC算法:

标记-清除算法(Mark-Sweep)

最基础的GC算法,将需要进行回收的对象做标记,之后扫描,有标记的进行回收,这样就产生两个步骤:标记和清除。这个算法效率不高,而且在清理完成后会产生内存碎片,这样,如果有大对象需要连续的内存空间时,还需要进行碎片整理,所以,此算法需要改进。

复制算法(Copying)

前面我们谈过,新生代内存分为了三份,Eden区和2块Survivor区,一般Sun的JVM会将Eden区和Survivor区的比例调为8:1,保证有一块Survivor区是空闲的,这样,在垃圾回收的时候,将不需要进行回收的对象放在空闲的Survivor区,然后将Eden区和第一块Survivor区进行完全清理,这样有一个问题,就是如果第二块Survivor区的空间不够大怎么办?这个时候,就需要当Survivor区不够用的时候,暂时借持久代的内存用一下。此算法适用于新生代

标记-整理(或叫压缩)算法(Mark-Compact)

和标记-清楚算法前半段一样,只是在标记了不需要进行回收的对象后,将标记过的对象移动到一起,使得内存连续,这样,只要将标记边界以外的内存清理就行了。此算法适用于持久代

常见的垃圾收集器: 

根据上面说的诸多算法,每天JVM都有不同的实现,我们先来看看常见的一些垃圾收集器:

JVM内存管理及垃圾回收详解

首先介绍三种实际的垃圾回收器:串行GC(SerialGC)、并行回收GC(Parallel Scavenge)和并行GC(ParNew)。

内容版权声明:除非注明,否则皆为本站原创文章。

转载注明出处:https://www.heiqu.com/a3fb10e63f17bf6399f40a8040d69c29.html