1.概述
Java中垃圾回收器所做的工作可以概括为两项:
1.检测出垃圾对象。
2.回收垃圾对象所使用的堆空间并还给程序。
垃圾回收的方法大概也能分为两种:
1.将活动的对象复制到另一个堆空间,再将原来的空间释放掉。
2.对活动的对象进行标记,再将没有被标记的对象进行回收。
在Java中,垃圾回收器有很多种实现,比如:引用计数收集器、跟踪收集器、压缩收集器、拷贝收集器、按代收集器以及自适应收集器等等;
2.引用计数收集器:
简单的说就是堆中每一个对象都有一个引用计数,当一个对象被创建并且该对象的引用被分配给了一个变量,那么该对象的引用计数会被置为1,当这个对象的引用被赋值给其它的变量时,该对象的引用计数会加1.任何引用计数为0的对象都会被当做垃圾,一个对象被回收后,他所引用的对象的引用计数就会减1,这样就有可能会因为一个对象的回收导致后续其他对象的垃圾收集行动。
优点:垃圾收集执行快,交织在程序的运行之中,对于程序不能被长时间打断的实时环境很有利!
缺点:相互引用的对象无法检测出来!
3.跟踪收集器
跟踪收集器简单的来说有点像一个链表,收集器会从根节点开始遍历,凡是被遍历到的对象都会被打上标记。最终没有被标记的对象就会被视为垃圾而被回收掉。
一个对象可以属于多个根节点(GC root),GC root有以下几种:
1. Class - 由系统类加载器(system class loader)加载的对象,这些类是不能够被回收的,他们可以以静态字段的方式保存持有其它对象。我们需要注意的一点就是,通过用户自定义的类加载器加载的类,除非相应的java.lang.Class实例以其它的某种(或多种)方式成为roots,否则它们并不是roots,.
2. Thread - 活着的线程
3. Stack Local - Java方法的local变量或参数
4. JNI Local - JNI方法的local变量或参数
5. JNI Global - 全局JNI引用
6. Monitor Used - 用于同步的监控对象
7. Held by JVM - 用于JVM特殊目的由GC保留的对象,但实际上这个与JVM的实现是有关的。可能已知的一些类型是:系统类加载器、一些JVM知道的重要的异常类、一些用于处理异常的预分配对象以及一些自定义的类加载器等。然而,JVM并没有为这些对象提供其它的信息,因此就只有留给分析分员去确定哪些是属于"JVM持有"的了。
4.压缩收集器
压缩收集器相当于跟踪收集器的加强版,它会将未被标记的的对象回收后再将活动的对象越过空闲区滑动到堆的另一端,所有被移动对象的引用也会跟着改变。这样能够简化消除堆内存碎片化的工作。但是会带来很大的性能消耗。代表性的有 G1(Garbage-First)垃圾收集器。
5.拷贝收集器
拷贝收集器把所有活动的对象复制到一个新的区域,拷贝过程中他们相互紧挨着布置,可以消除他们在原有空间的空隙。在这种方案中,堆被分为了两个区域。任何时候都只使用一个区域,直到那个区域被耗尽,这时候程序运行被中止,堆被遍历,遇到活动的对象就拷贝到另一个区域,当拷贝过程结束之后程序恢复运行。
6.按代收集器
在一个程序中一般创建的大多数对象的生命周期都较短,同时一个程序中也会创建生命周期很长的对象。我们知道简单的拷贝收集器运行时会将所有的对象来回拷贝,这样将会加大性能的消耗。
按代收集器将对象按寿命区分,更多的收集哪些年幼的对象。按代收集器将堆分为几个子堆,分别对应不同的寿命。当一个对象在一次收集过程中没有被回收,那么他的年龄将会加大,放到另一个对应寿命的堆中。
按代收集器可以应用于标记清除算法和拷贝算法,不管是哪一种都能很好的提高垃圾收集器的性能。
7.自适应收集器
自适应收集器可以监视堆中的情况,根据堆中的情况切换不同的算法或者堆的结构等方法来实现垃圾回收。使用自适应收集器,Java虚拟机设计者不需要只使用一种特定的垃圾收集算法,可以使用多种技术,以便在每种技术最擅长的领域来使用他们!
引用资料:
1.《深入JAVA虚拟机》
2. http://www.yourkit.com/docs/80/help/gc_roots.jsp