JAVA是一门令人省心的语言,所以我们平常创建完对象之后,不需要像C++等语言一样,需要对创建的对象进行释放操作.而是交给虚拟机的垃圾回收器.

垃圾回收器的回收时刻:

1当JAVA虚拟机内存不足时  

3 当程序结束时,调用的所有资源也会交还给系统.

记住,正常情况下,不到JAVA虚拟机内存快满的时候,是不会执行垃圾回收的.


哪些对象会被回收?

那些不再被引用的对象.

比如那些new 出来的对象,没有被引用,或者创建时引用,而后引用又被指向NULL的对象.


finalize()方法是什么,有什么用,什么时候调用?

finalize()方法是Object类就有的,当系统回收器要释放对象的,首先会执行它的finalize()方法.


既然JAVA中一切都是对象,那么理应所有的对象都会通过垃圾回收器释放掉,为什么还需要finalize()方法?

原因是,JAVA有可能在分配某些内存的时候,使用的是"本地方法",这些方法由c和c++编写,猜想是为了进行硬件级的操作,所以这些空间的申请不是通过对象的方式申请的,必须通过调用某些方法(这些方法也是用C的方式回收掉调用的内存)来释放,而这些方法,就可以写在finalaize()中.

finalize的用法,最好搭配一个标志位(又称终结条件),在需要的时候才调用释放逻辑.

Book类,book类在回收之前必须执行CheckIn操作,否则finalize就会提示

<span style="font-size:14px;">public class Book {
	//检查位
	boolean checkeOut = false;
	public Book() {
		checkeOut=checkeOut;
		// TODO Auto-generated constructor stub
	}
	public void checkIn(){
		checkeOut=false;
	}
	@Override
	protected void finalize() {
		// TODO Auto-generated method stub
		if (checkeOut) {
			System.out.println("Error: checked out");
		}
	}
}</span>



简单理解JAVA垃圾回收的工作原理

JAVA  new出来的对象分配在堆上的(关于栈 堆的知识 自行查阅),堆就像一个传送机,不断地把一个个对象加进堆中. 那么你一定有疑问了,如果堆满了怎么办?那么就要开始垃圾回收机制:

第一步:找到那些没有被引用,不再被需要的对象,有两种方式:

1:引用计数法,每个对象都有一个引用计数器,当有引用连接到对象的时候,计数器+1;当引用离开作用域或者被指向NULL的 时候-1.   垃圾回收器会遍历所有对象的计数器,那些为0的就是不再被需要的对象.

优点:简单

缺点:速度很慢  ,存在缺陷,当存在对象之间互相应用时(比如A对象的成员中引用了B对象,而B对象的成员中引用了A对象,两者都不再被需要了,但是他们的计数仍然不是0)

2遍历 堆栈  和  静态存储区中的引用, 再遍历这些引用指向的对象中的引用,再.....递归下去,就能够找到所有活的引用.

优点:稍微快速,解决了上面的缺陷


第二步,JAVA中就是通过第二种方式找到不需要的对象的,那么如何把这些对象踢出内存,并且让剩下的空间重新排列整理,腾出新的堆来呢?

"停止-复制":  先暂停当前的程序,然后,将存活的对象从原堆复制到另外一个堆,此时,新堆是连续的.

这非常的消耗空间和时间,所以当垃圾多的时候,使用这种策略

"标记-清扫":同样是从堆栈和静态存储区出发,遍历出所有活的对象.  给每一个活着的对象标记.当标记工作全部完成之后,就会清理掉那些没有被标记的对象.剩下的空间是不连续的,所以还要整理空间来腾出空间.

注意,两者都是需要停止程序进行的


当垃圾回收器第一次启动时,它执行的是“停止-复制”,因为这个时刻内存有太多的垃圾。然后Java虚拟机会进行监视,如果所有对象都很稳定,垃圾回收器的效率降低的话,就切换到“标记-清扫”方式;同样,Java虚拟机会跟踪“标记-清扫”效果,要是堆空间出现很多碎片,就会切换到“停止-复制”方式。这就是所谓的“自适应”技术。

其实仔细想一下,“停止-复制”和“标记-清扫”无非就是:“在大量的垃圾中找干净的东西和在大量干净的东西里找垃圾”。不同的环境用不同的方式,这样做完全是为了提高效率,要知道,无论哪种方式,Java都会先暂停程序的运行,所以,垃圾回收器的效率其实是很低的。Java用效率换回了C++没有的垃圾回收器和运行时的灵活,我认为这是明智的选择(虽然它只跟内存有关),随着硬件的飞速发展,我相信,开发时间要比运行效率重要得多!


看<java编程思想>读书笔记,最后一段有点难理解,直接引用了网上的一些解释.

我觉得初学者阶段只要有所了解就可以了,先把java各方面的基础知识先掌握好了,然后再深入了解JAVA虚拟机,那样对你的技术栈才是真正的提升. 先提升知识广度,当你对JAVA对计算机有了一定的了解之后,再进行探索深度.两者是相互辅助的.