这还是一个搭积木的过程,看《Java 编程思想》这本书,看到了垃圾回收相关的章节,半懂不懂地记下一点东西,可能现在写的之后看会有很多错误的地方,但是先写下来再说。
关于清除、终结和垃圾回收
在 C 与 C++这两门语言(或者说就是一门语言,毕竟后者就是前者加入了面向对象特性的升级版)中,最难为人的地方无非就是指针的使用和内存的分配与管理。Java 在这一方面减轻了许多程序员的负担,其一是 Java 没有指针这个东西,其二内存的分配与管理上引入了垃圾回收(garbage collection)的概念,使得程序编写过程中可以相对轻松地不用管内存何时释放这个问题,由程序自动回收不再使用的内存,如此云云。
今天看了相关的内容,产生了几个问题,第一,自己还是不太明白这个内存回收的具体机理,它是怎么知道程序不会再使用已经使用过的内存了呢?其二,既然已经有了这个机制,那是不是就可以当一个甩手掌柜,什么事都交给它了呢?既然如此那为什么还会有一个终结(finalize())函数存在呢?
首先说明以下这个问题,第一,Java 作为一门面向对象语言,类的构造函数是有的,对象的初始化借助构造函数完成,大部分情况下对象占用的内存释放借助垃圾回收机制完成。第二,finalize()绝对不等于 C++类里的析构函数。需要明确的点是,C++里的对象一定会被析构函数销毁,但是 Java 里的对象并不一定总是会被垃圾回收掉。
- 对象可能不被回收
- 垃圾回收不等于“析构”
- 垃圾回收只与内存有关
说实话有点蒙:什么时候对象不会被回收?垃圾回收不等于析构,那么它又是什么?
第一个问题,垃圾回收只会回收通过 new 关键字申请的对象所占用的内存,对于不用这种方式获得的特殊内存,应该定义一个finalize()函数,通过在垃圾回收准备回收内存时先调用finalize()来进行一些清除操作,使得在下一次垃圾回收时使得真正回收对象的内存。
由此产生的新的问题,除了 new 以外申请内存的方式是什么?finalize()具体的操作过程是什么?
**只要程序没有濒临存储空间用完的那一刻,对象占用的空间就总也得不到释放。如果程序执行结束,并且垃圾回收器一直都没有释放你创建的任何对象的存储空间,则随着程序的退出,那些资源会全部交还给操作系统。这个策略是恰当的,因为垃圾回收本身也有开销,要是不使用它,那就不用支付这部分开销了。**也就是说,只要内存够用,垃圾回收机制是不会调动的。
finalize()的真正用途:垃圾回收器存在的唯一原因就是回收程序不再使用的内存,而只要是与垃圾回收相关的行为(包括finalize()),也必须要和内存及其回收有关。
也就是说,内存的回收最后一步一定是垃圾回收,但是在少部分情况下需要使用finalize()来进行部分清除工作,之后由垃圾回收来完成内存回收。
finalize()的使用场景是在 Java 中可能调用了 C/C++代码,由于这两种语言内存空间不会自动释放,需要在finalize()中调用释放内存空间的对应函数。
所以finalize()不是一个很常用的清除工作的执行方法,只有在存在不能自动释放内存的时候会使用一下。
finalize()的调用是自动进行的,发生在垃圾回收执行之前,可以在finalize()里面加入一些动作,通过动作找 bug。(所谓“终结条件的验证”)当然垃圾回收只有内存空间不够才会执行,可以通过System.gc()强制执行垃圾回收以达到执行finalize()的目的。
在大部分情况下,垃圾回收都是不用担心的,因为垃圾回收器的存在,基本上代替了析构函数的作用,但是当你想进行回收存储空间以外的清楚工作,你就得明确定义一个相关功能的函数,不能是finalize(),因为它不能手动调用。相比之下反而没有析构好。虽然这种情况很少很少。
垃圾回收器究竟是如何工作的?
Java 除了基本类型之外的对象都是创建在堆上的,回忆一下 C/C++的堆内存申请与释放过程,不难理解相比代价高昂的使用堆内存的两种语言,Java 的垃圾回收机制十分高效快速。
内存空间的释放竟然会影响内存的分配……