(一)java GC的意义
1、GC 可以有效的防治内存泄露
2、减轻程序员编程负担
(二)GC 潜在缺点
1、GC 开销影响程序性能
2、不能保证100%回收无用内存
(三)哪些内存需要被回收?
在主流的商用程序语言的主流实现中都是通过可达性分析来判断对象是否存活(判断哪些对象可以回收)。
算法基本思想:通过一系列的称为“GC Roots” 的对象作为起始点,从这些节点开始向下搜索,搜索所走过的路劲称为引用链,当一个对象到GC Roots 没有任何引用链相连时则证明此对象是不可用的(可被回收的)。[1]
[2]
【可以作为GC roots 的对象】
1、虚拟机栈(栈帧中的本地变量表)中引用的对象
2、方法区中静态类属性引用的对象
3、方法区中常量引用的对象
4、本地方法栈中(一般说的native 方法)引用的对象
事实上GC并不需要一个不漏地检查完所有GC roots,虚拟机应当是有办法直接得到哪些地方存放着对象引用。在HotSpot的实现中,是使用一组成为OopMap的数据结构来达到这个目的.
在类加载完成的时候,HotSpot就把对象内什么偏移量上是什么类型的数据计算出来,在JIT编译过程中,也会在特定的位置记录下栈里和寄存器里哪些位置是引用。这样GC在扫描时就就可以直接得知这些信息了。[3]
(二)何时进行垃圾回收?Java的垃圾回收机制是Java虚拟机提供的能力,用于在空闲时间以不定时的方式动态回收无任何引用的对象占据的内存空间。
System.gc()
Runtime.getRuntime().gc()
上面的方法调用时用于显式通知JVM可以进行一次垃圾回收,但真正垃圾回收机制具体在什么时间点开始发生动作这同样是不可预料的,这和抢占式的线程在发生作用时的原理一样。
(三)如何进行垃圾回收?
当前商业虚拟机的垃圾收集都采用“分代收集”算法。
算法思想:根据对象存活周期的不同将内存划分为几块。一般把java 堆分为新生代和老年代
新生代:主要是用来存放新生的对象。
老年代:主要存放应用程序中生命周期长的内存对象。(大对象、长期存活的对象)
在新生代中,每次垃圾收集时都发现有大批对象死去,只有少量存活,那就选用复制算法,只需要付出少量存活对象的复制成本就可以完成收集。而老年代中因为对象存活率高、没有额外空间对它进行分配担保,就必须使用“标记-清理”或“标记-整理”算法来进行回收。
参考文献:
[1].《深入理解java虚拟机》P64-80
[2]. http://www.kuqin.com/java/20110906/264406.html
[3]. http://www.kuqin.com/java/20110906/264406.html