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对计算机有了一定的了解之后,再进行探索深度.两者是相互辅助的.