注:该博客或为自己所写,以供学习之用
注:博客中部分来源于《深入理解java虚拟机》
一.垃圾收集器关注的问题
1.哪些内存需要回收?
java GC主要关注的是堆内存区
2.什么时候回收?
3.如何回收?
二.判断对象是否存活的算法
1.引用计数器算法
算法思想:给对象添加一个引用计数器,每当有一个地方引用它时,计数器值就加1;当引用失效时,计数器的值就减1;任何时刻计数器为0的对象就是不可能在被使用的。
2.可达性分析算法(根搜索算法)
java语言中使用根搜索算法(GC Roots Tracing)判定对象是否存活。其算法基本思路是:通过一系列的名为“GC Roots”的对象作为起始点,从这些节点开始向下搜索,搜索所走过的路径称为引用链,当一个对象到GC Roots没有任何引用链相连时,则证明此对象是不可用的。如下图:
三.再谈引用
在jdk1.2之后,java对引用的概念进行了扩充,将引用分为强引用(Strong reference),软引用(Soft Reference),弱引用(weak reference),虚引用(Phantom reference)四种,这四种引用强度依次逐渐减弱。
* 强引用就是指在程序代码之中普遍存在的,类似Object obj=new Object();这类的引用,只要强引用还存在,垃圾回收器永远不会回收掉被引用的对象
* 软引用用来描述一些还在用,但并非必须的对象。对于软引用关联的对象,在系统将要发生内存溢出异常之前,将会把这些对象列进回收范围之中并进行第二次回收。
* 弱引用也是用来描述非必须对象的,但是它的强度比软引用更弱一些,被弱引用关联的对象只能生存到下一次垃圾回收之前。当垃圾回收器工作时,无论当前内存是否足够,都会回收掉只被弱引用关联的对象。
* 虚引用也称为幽灵引用或者幻影引用,它是最弱的一种引用关系。一个对象是否有虚引用的存在,完全不会对其生存时间构成影响,也无法通过虚引用来取得一个对象实例。为一个对象设置虚引用关联的唯一目的就是希望在这个对象被收集器回收时收到一个系统通知。
四.生存还是死亡?
五.方法区的垃圾回收(永久代垃圾回收)
1.永久代的垃圾回收主要回收两部分内容:废弃常量和无用的类。回收废弃常量与回收java堆中的对象非常类似。
2.“无用的类“一般需要满足下面三个条件:
* 该类所有的实例都已经被回收,也就是java堆中不存在该类的任何实例
* 加载该类的ClassLoader已经被回收
* 该类对应的java.lang.Class对象没有在任何地方被引用,无法在任何地方通过反射访问该类的方法。
3.参数使用情况:
-Xnoclassgc:控制是否回收无用类
-verbose:class、-XX:+TraceClassLoading、-XX:+TraceClassUnLoading:查看类加载和卸载信息
六.垃圾回收算法(标记-清除算法、复制算法、标记-整理算法、分代收集算法)
1.标记-清除算法
基本思想:首先标记出所有需要回收的对象,在标记完成后统一回收所有被标记的对象。
2.复制算法
基本思想:将可用内存按照容量划分为大小相等的两块,每次只使用其中的一块。当一块的内存用完了,就将还存活着的对象复制到另一块上面,然后再把已使用过的内存空间清理掉。
注:由于新生代中的对象98%是“朝生夕死”的,所以并不需要按照1:1的比例来划分内存空间(HotSpot虚拟机默认Enden和Survivor的大小比例是8:1),而是将没存分为一块较大的Eden空间和两块较小的Survivor空间,每次使用Enden和其中一块Survivor。
垃圾回收时,将Eden和Survivor中存活着的对象一次性的复制到另外一块Survivor空间上,最后清理掉Enden和刚才用过的Survivor空间。
3.标记-整理算法
基本思想:先进行标记,让所有存活的对象都向一端移动,然后直接清理掉端边界以外的内存。
4.分代收集算法(常用)
基本思想:根据对象存活周期的不同将内存划分为几块。一般是把java堆分为新生代和老年代,然后根据各个年代的特点采用最适当的收集算法。
新生代:死去的对象较多,存活的较少,选用复制算法
老年代:标记-清理或者标记-整理
总结:
七.内存回收与分配策略
1.对象优先在Eden区上分配
2.大对象直接进入老年代
虚拟机提供了一个-XX:PretenureSizeThreshold参数,令大于这个设置值的对象直接在老年代分配。
3.长期存活的对象将进入老年代
虚拟机给每个对象定义了一个年龄计数器。如果对象在Eden出生并经过一次MinorGC后任然存活,并且被Survivor容纳的话,将移动到Survivor空间中,并且对象年龄设为1.对象在Survivor区中每“熬过”一次MinorGC,年龄增加1岁,当他的年龄增加到一定程度(默认15,由-XX:MaxTenuringThreshold参数指定),就将会晋升到老年代。
注:新生代GC:Minor GC 老年代GC:Major GC/Full GC