Java垃圾回收机制通常包含近十种算法。对这些算法中的多数,咱们没必要予以关心。只有其中最简单的一个:引用计数法,与编码有关。算法
一.谁在作Garbage Collection?函数
在C++里,释放内存是手动处理的,要用delete运算符来释放分配的内存。这是流行的说法。确切地说,是应用认为不须要某实体时,就需用delete告诉系统,能够回收这块空间了。这个要求,对编码者来讲,是件很麻烦、很难作到的事。随便上哪一个BBS,在C/C++版块里老是有一大堆关于内存泄漏的话题。编码
Java采用一种不一样的,很方便的方法:Garbage Collection。Java垃圾回收机制放在JVM里。JVM彻底负责垃圾回收事宜,应用只在须要时申请空间,而在抛弃对象时没必要关心空间回收问题。spa
二.对象在啥时被丢弃?code
在C++里,当对象离开其做用域时,该对象即被应用抛弃。对象
是对象的生命期再也不与其做用域有关,而仅仅与引用有关。进程
Java的垃圾回收机制通常包含近十种算法。对这些算法中的多数,咱们没必要予以关心。只有其中最简单的一个:引用计数法,与编码有关。内存
一个对象,能够有一个或多个引用变量指向它。当一个对象再也不有任何一个引用变量指向它时,这个对象就被应用抛弃了。或者说,这个对象能够被垃圾回收机制回收了。作用域
这就是说,当不存在对某对象的任何引用时,就意味着,应用告诉JVM:我不要这个对象,你能够回收了。字符串
JVM的垃圾回收机制对堆空间作实时检测。当发现某对象的引用计数为0时,就将该对象列入待回收列表中。可是,并非立刻予以销毁。
三.丢弃就被回收?
该对象被认定为没有存在的必要了,那么它所占用的内存就能够被释放。被回收的内存能够用于后续的再分配。
可是,并非对象被抛弃后立即被回收的。JVM进程作空间回收有较大的系统开销。若是每当某应用进程丢弃一个对象,就当即回收它的空间,势必会使整个系统的运转效率很是低下。
前面说过,JVM的垃圾回收机制有多个算法。除了引用计数法是用来判断对象是否已被抛弃外,其它算法是用来肯定什么时候及如何作回收。JVM的垃圾回收机制要在时间和空间之间作个平衡。
所以,为了提升系统效率,垃圾回收器一般只在知足两个条件时才运行:即有对象要回收且系统须要回收。切记垃圾回收要占用时间,所以,Java运行时系统只在须要的时候才使用它。所以你没法知道垃圾回收发生的精确时间。
四.没有引用变量指向的对象有用吗?
前面说了,没挂上引用变量的对象是被应用丢弃的,这意味着,它在堆空间里是个垃圾,随时可能被JVM回收。
不过,这里有个不是例外的例外。对于一次性使用的对象(有些书称之为临时对象),能够不用引用变量指向它。举个最简单也最多见的例子:
System.out.println(“I am Java!”);
就是建立了一个字符串对象后,直接传递给println()方法。
五.应用能干预垃圾回收吗?
许多人对Java的垃圾回收机制不放心,但愿在应用代码里控制JVM的垃圾回收运做。这是不可能的事。对垃圾回收机制来讲,应用只有两个途径发消息给JVM。第一个前面已经说了,就是将指向某对象的全部引用变量所有移走。这就至关于向JVM发了一个消息:这个对象不要了。第二个是调用库方法System.gc(),多数书里说调用它让Java作垃圾回收。
第一个是一个告知,而调用System.gc()也仅仅是一个请求。JVM接受这个消息后,并非当即作垃圾回收,而只是对几个垃圾回收算法作了加权,使垃圾回收操做容易发生,或提前发生,或回收较多而已。
但愿JVM及时回收垃圾,是一种需求。其实,还有相反的一种须要:在某段时间内最好不要回收垃圾。要求运行速度最快的实时系统,特别是嵌入式系统,每每但愿如此。
Java的垃圾回收机制是为全部Java应用进程服务的,而不是为某个特定的进程服务的。所以,任何一个进程都不能命令Java垃圾回收机制作什么、怎么作或作多少。
六.对象被回收时要作的事
一个对象在运行时,可能会有一些东西与其关连。所以,当对象即将被销毁时,有时须要作一些善后工做。能够把这些操做写在finalize()方法(常称之为终止器)里。
protected void finalize()
{
// finalization code here
}
这个终止器的用途相似于C++里的析构函数,并且都是自动调用的。可是,二者的调用时机不同,使二者的表现行为有重大区别。C++的析构函数老是当对象离开做用域时被调用。这就是说,C++析构函数的调用时机是肯定的,且是可被应用判知的。可是,Java终止器倒是在对象被销毁时。由上所知,被丢弃的对象什么时候被销毁,应用是没法获知的。并且,对于大多数场合,被丢弃对象在应用终止后仍未销毁。
在编码时,考虑到这一点。譬如,某对象在运做时打开了某个文件,在对象被丢弃时不关闭它,而是把文件关闭语句写在终止器里。这样作对文件操做会形成问题。若是文件是独占打开的,则其它对象将没法访问这个文件。若是文件是共享打开的,则另外一访问该文件的对象直至应用终结仍不能读到被丢弃对象写入该文件的新内容。
至少对于文件操做,编码者应认清Java终止器与C++析构函数之间的差别。
那么,当应用终止,会不会执行应用中的全部finalize()呢?据Bruce Eckel在Thinking in Java里的观点:“到程序结束的时候,并不是全部收尾模块都会获得调用”。这还仅仅是指应用正常终止的场合,非正常终止呢?
所以,哪些收尾操做能够放在finalize()里,是须要酌酎的。