参考文章:
http://www.charlesxiao.top/2015/07/29/%E6%B5%85%E6%9E%90java%E5%86%85%E5%AD%98%E7%AE%A1%E7%90%86%E6%9C%BA%E5%88%B6/
http://www.infoq.com/cn/articles/cf-java-garbage-references
http://blog.sina.com.cn/s/blog_6145ed810100stu7.html
GC机制的优势:
c语言需要程序员去分配内存,释放内存。这就导致,如果已分配的内存始终没有得到释放,会发生内存泄漏的问题。
java是由jvm自动的分配内存和释放内存,自动回收不再被引用的对象。
调用System. gc()方法来建议执行垃圾收集器
垃圾回收器的运行时间是不确定的,由JVM决定,在运行时是间歇执行的。虽然可以通过System.gc()来强制回收垃圾,但是这个命令下达后无法保证JVM会立即响应执行,但经验表明,下达命令后,会在短期内执行你的请求。JVM通常会感到内存紧缺时候去执行垃圾回收操作。
垃圾回收最基本的做法是分代回收:
JVM将堆分成了两个世代: 新生、老年,不同世代采用不同垃圾回收算法。
新生代又分为: Eden(进行内存分配)、Servivor1、Servivor2, 两个Survivor 区相对地作为为From 和 To 逻辑区域, 当Servivor1作为 From 时 , Servivor2 就作为 To, 反之亦然。两个存活区中始终有一个是空白的。
年轻对象存放在年轻代,采用Minor GC(指从年轻代空间(包括 Eden 和 Survivor 区域)回收内存); 长期存活的年老对象以及大对象直接存放在年老代,采用Full GC(Full GC == Major GC指的是对老年代/永久代的stop the world的GC),回收速度慢。
当Eden区满的时候 GC执行,这时会将 Eden 区和 From 区中还被引用的对象会被移到 To区 ,个别大对象和部分From对象在To已满的情况下会被放到Old区。
JVM维护一个对象的年龄来进行对象的内存区域转移,从Eden-Survivor-老年代。
finalize()方法的工作原理是:每一个对象都有一个finalize( )方法,这个方法是从Object类继承来的。一旦垃圾回收器准备好释放对象占用的存储空间,将首先调用并且只能调用一次该对象的finalize()方法(通过代码System.gc()实现),并且在下一次垃圾回收动作发生时,才会真正回收对象占用的内存。所以如果我们重载finalize()方法就能在垃圾回收时刻做一些重要的清理工作或者自救该对象一次(只要在finalize()方法中让该对象重新和引用链上的任何一个对象建立关联即可)。finalize()方法用于释放用特殊方式分配的内存空间,这是因为我们可能在java中调用非java代码来分配内存,比如Android开发中调用NDK。那么,当我们调用C中的malloc()函数分配了存储空间,我们就只能用free()函数来释放这些内存,这样就需要我们在finalize()函数中用本地方法调用它。
总结:
理解了垃圾回收的前提是理解Java运行时的内存堆栈模型。
理解Java垃圾回收的目的是为了对Java内存管理有个认识,在编程时更有效的使用内存。
不建议为了垃圾回收,手动编写大量代码,这是很愚蠢的做法。可以通过简单的方式去影响即可。