引用计数法判定一个对象是否为垃圾对象的方式是为每一个对象设置一个引用计数器,每当一个对象引用它时,这个引用计数器就加1,引用失效时,则其减1,当引用计数器为0时则为垃圾对象.这种方式不能处理循环引用。
通过一系列的GCRoots开始向下搜索,对于没有GCRoots能够达到的对象则判定为垃圾对象。java语言中GCRoots包括有以下几种:
虚拟机栈,本地方法栈中引用的对象(正在用的对象)方法区中静态属性引用的对象。常量区中引用的对象方法区中的垃圾对象主要为"废弃常量"和"无用的类"。 "废弃常量"的判定是当前系统中没有任何对象引用了这个常量 "无用的类"的判断标准为:
该类的所有实例都已经被回收加载该类的classloder已经被回收改类对应的Class对象没有在任何地方被引用首先标记出所有需要回收的对象,在标记后统一回收所有的被标记的对象
复制算法是指将内存化分为相等的两块,每一次只使用其中一块,每次垃圾回收时将还存活的对象移到另一块中。实际上虚拟机上的实现是将内存分为新生代和老年代,新生代中又分为Eden区和两个survivor区,每次使用的是Eden区和其中一个survivor区,hotspot默认的eden和survivor区的比值为8:1,因此每次只浪费10% 。
标记整理算法先标记出所有需要回收的对象,然后将所有存活的对象向一端移动,然后直接清理掉边界以外的内存。
hotspot通过OopMap来直接得知那些地方存放着对象引用。 在进行GCRoots时可能会由于程序在运行而导致引用关系的变化,并且hotspot不能为每条指令生成对象的OopMap。而在HotSpot实现时采用的是"安全点",只需要将正在执行的线程"跑到"安全点,就可以执行gc对应的操作,安全区域,当线程执行到安全区域时,首先标定自己为Safe Region状态的线程,在这段时间JVM执行gc操作时,就不需要将已经在安全区域的线程运行到对应的安全点去。
Serial收集器是一个单线程的收集器,在它进行垃圾回收时,需要停止所有工作线程,直至其收集结束
ParNew收集器是Serial收集器的多线程版本.
Parallel Scavenge收集器主要目标是达到一个可控制的吞吐量。可以用-XX:SurvivorRatio设置吞吐量,-XX:PretenureSizeThreshold设置晋升老年代的年龄,-XX:MAXGCPauseMillis设置最大垃圾回收停顿时间。主要适合在后台运算而不需要太多交互的任务。
Serial Old收集器是Serial收集器的老年代版本,这个收集器的主要意义是在于给Client模式下的虚拟机使用,在server模式下作为CMS的后备方案,如果CMS出错则采用Serial Old收集器。
Parallel Old收集器是Parallel Scavenge收集器的老年代版本。
算法实现主要是有4个步骤:
初始标记并发标记重新标记并发清除初始标记标记的是GC Roots能直接关联到的对象。并发标记则是进行 GC Roots tracing的过程.重新标记是修正并发标记期间标记产生变动的那一部分对象的标记记录。并发清除则采用标记-清除算法对标记好的对象清除。