5.5 清理:终结处理和垃圾回收
Java有垃圾回收机制负责回收无用对象占据的内存资源。但是也有特殊情况,加入对象不是并非使用new获得一块特殊的内存区域,由于垃圾回收器只释放那些经由new分配的内存,所以它不知道该如何释放该对象的这块“特殊”内存。为了应对这种情况,Java允许在类中定义一个名为finalize()的方法,工作原理:一旦垃圾回收器准备好释放对象的占用的存储空间,将首先调用其finalize()方法。并且在下一次垃圾回收动作发生时,才会真正回收对象占用的存储空间。所以想回收非new 获得的内存区域,在finalize()中添加回收方法,当垃圾回收发生时(不能保证一定发生),finalize()得到调用,“特殊”内存得到回收。
对finalize()的需求限制在一种特殊情况:即通过某种创建对象方式以外的方式为对象分配了存储空间。主要发生在使用本地方法的情况下。本地方法是一种在Java中调用非Java代码的方式(Java中有些方法不是Java实现,采用C或者C++实现。本人注解,想了解的可以看这篇博客
http://blog.csdn.net/lansine2005/article/details/5753741)
Java有垃圾回收机制负责回收无用对象占据的内存资源。但是也有特殊情况,加入对象不是并非使用new获得一块特殊的内存区域,由于垃圾回收器只释放那些经由new分配的内存,所以它不知道该如何释放该对象的这块“特殊”内存。为了应对这种情况,Java允许在类中定义一个名为finalize()的方法,工作原理:一旦垃圾回收器准备好释放对象的占用的存储空间,将首先调用其finalize()方法。并且在下一次垃圾回收动作发生时,才会真正回收对象占用的存储空间。所以想回收非new 获得的内存区域,在finalize()中添加回收方法,当垃圾回收发生时(不能保证一定发生),finalize()得到调用,“特殊”内存得到回收。
对finalize()的需求限制在一种特殊情况:即通过某种创建对象方式以外的方式为对象分配了存储空间。主要发生在使用本地方法的情况下。本地方法是一种在Java中调用非Java代码的方式(Java中有些方法不是Java实现,采用C或者C++实现。本人注解,想了解的可以看这篇博客
5.5.4. 垃圾回收器如何工作
垃圾回收器对于提高对象的创建速度,有明显的效果。在某些Java虚拟机中,堆的实现截然不同,它更像一个传送带,每分配一个对象,就往前移动一格。这就意味着对象存储空间的分配速度非常快。回收器介入时,当它工作一面回收空间,一面使堆中的对象紧凑排列,这样“堆指针”就更容易靠近传送带开始处。通过垃圾回收器对对象的重新排列,实现了一种高速的,有无限空间可分配的堆模型。
垃圾回收技术:
1、引用计数:每个对象都含有一个引用计数器,当有引用连接至对象时,引用计数加1,当引用离开作用域或被置为Null时,引用计数减1.缺陷:当对象之间存在循环引用,可能出现对象应该被回收,但引用计数不为0。但这项开销在整个程序生命周期中将持续发生,垃圾回收器会在含有全部对象的列表上遍历,当发现某个对象的引用计数为0,就释放其空间。引用计数是种简单但速度很慢的垃圾回收技术。
2、停止-复制:暂停程序的运行,将存活对象从当前堆复制到另外一个堆,没有复制的就是垃圾。当对象复制到新堆时,就是紧凑排列的,当执行时,指向对象的引用必须修正。缺点:程序进入稳定后,垃圾较少,如此转移存活堆方式浪费空间和时间。一些Java虚拟机会进行检查,要是没有新垃圾得产生就进入另外一种方式:标记-清扫
3、标记-清扫:我觉得是第一种方法的改良,其思路同样从堆栈和静态存储区出发,遍历所有引用,进而找出所有存活的对象,然后标记,过程中不进行回收,当标记完成后,清扫没有标记的对象。不会发生任何复制动作,所以剩下的堆空间不是连续的,想得到连续空间,就得重新整理剩下的对象。
自适应的、分代的、停止-复制、标记-清扫式垃圾回收器:其实就是自动检查,如果垃圾多久切换停止-复制,垃圾少就切换标记-清扫。
4、Just-in-time JIT技术:这种技术可以把程序全部或部分翻译为本地机器码,程序运行速度得以提升,当需要装载某个类时,编译器会先找到.class文件,然后将该类的字节码装入内存。此时有两种方案可选择:1.、编译所有代码,担忧两个缺陷,这种加载动作散落在整个程序生命周期内,累加起来需要更多时间。会增加可执行代码的长度。这将导致页面调度,从而降低程序速度。2、惰性评估:即时编译器只在需要的时候编译代码,这样,从不执行的代码压根就不会被JIT编译。新版HotSpot中采用了类似的方法,代码每执行一次都会优化,所以,执行越多,程序越速度越快。