Java垃圾回收机制(扫盲篇)

来源:互联网 发布:人工智能介绍英文文章 编辑:程序博客网 时间:2024/06/16 17:01

Java语言的一个显著特点就是引入了垃圾回收机制,使c++程序员最头疼的内存管理的问题迎刃而解,它使得Java程序员在编写程序的时候不再需要考虑内存管理。由于有个垃圾回收机制,Java中的对象不再有”作用域”的概念,只有对象的引用才有”作用域”。垃圾回收可以有效的防止内存泄露,有效的利用可以使用的内存。

垃圾回收器通常是作为一个单独的低级别的线程运行,不可预知的情况下对内存堆中已经死亡的或者长时间没有使用的对象进行清除和回收,程序员不能实时的调用垃圾回收器对某个对象或所有对象进行垃圾回收。回收机制有分代复制垃圾回收和标记垃圾回收,增量垃圾回收等。

使用Java无须担心如何销毁对象,即当Java不再使用某个对象时,它会自动进行垃圾回收。当程序运行时自动检查整个内存,检查内存中哪些对象引用不再被使用。一旦检查出来后,便会安全删除这些对象。然而,由于垃圾回收需要占用系统的资源,所以它可能会影响应用程序代码的执行,即如果在执行应用程序代码的过程中,执行垃圾回收,则应用程序代码的执行时间可能延长,这会导致程序运行的延迟。由于不知道何时会进行垃圾回收,因此延迟的时间也是不可预知的。实时应用程序对时间的要求非常严格,即它们必须在确定的、已知的延迟条件下,执行应用程序代码,因此垃圾回收所引起的不可预知的延迟就成为了一个实时程序致命的问题。垃圾回收的主要问题是程序无法估计时间延迟导致程序执行的延迟。通过更频繁的进行垃圾回收,就可以限制最大延迟时间,因此使垃圾回收成为可预知的。

1)、何时对象被丢弃

Java语言规范没有明确地说明JVM使用哪种垃圾回收算法,但是任何一种垃圾回收算法一般要做两件基本的事情:一是发现无用对象;二是回收无用对象占用的内存空间,使该空间可被程序再次使用。根集:正在执行的Java程序可以访问的引用变量的集合(包括局部变量、参数、类变量),程序可以使用引用变量访问对象的属性和调用对象的方法。垃圾收集首先要确定从根开始哪些是可达的和哪些是不可达的,从根集可达的对象都是活动对象,它们不能作为垃圾被回收,这也包括从根集间接可达的对象。而从根集通过任意路径不可达的对象符合垃圾回收的条件,应该被回收。Java的垃圾回收机制一般包括近10种算法。其中最简单的一个:引用计数法,该方法是唯一没有使用根集的垃圾回收算法,该算法使用引用计算器来区分存活对象和不再使用的对象。也就是说,当应用程序创建引用以及引用超出范围时,JVM必须适当增减引用数。当某对象的引用数为0时,便可以进行垃圾回收。在使用JVM的垃圾回收机制对堆空间做实时检测的时候,发现当某对象的引用计数为0时,就将该对象列入待回收列表中。

2)、对象被丢弃,是否立即回收

如果一个对象赋值为null或者重新定向了该对象的引用者,则该对象被认定为没有存在的必要了,那么它所占用的内存就可以被释放了。被回收的内存可以用于后续的再分配。但是,并不是对象被抛弃后立即被回收的。用JVM进程做空间回收是有较大的系统开销的。在实际的项目开发中,丢弃一个对象,创建一个对象,这样的操作不计其数。如果每当某一应用程序丢弃一个对象,JVM就立即回收它的空间,势必会使整个系统的运转效率非常低下。JVM中除了引用计算法是用来判断对象是否已被抛弃外,其他算法是用来确定何时及如何进行回收。JVM的垃圾回收机制要在时间和空间之间做个平衡。因此,为了提高系统效率,垃圾回收器通常只在满足两个条件时才运行:有对象要回收和系统需要回收。切记垃圾回收要占用时间,因此,Java运行时,系统只在需要的时候才使用它。因此用户无法知道垃圾回收发生的精确时间。

3)、垃圾回收

许多人对Java的垃圾回收不放心,希望在应用代码里控制JVM的垃圾回收运作,这是不可能的事。对垃圾回收机制来说,应该只有两个途径发消息给JVM。一是将指向某对象的所有引用变量全部移走。这就相当于向JVM发了一个消息:这个对象不再需要了。第二个是调用库方法System.gc(),GC即垃圾回收机制是指JVM用于释放那些不再使用的对象占用的内存。JVM接到Syste.gc()发来的消息后,并不立即进行垃圾回收,而只是对几个垃圾回收算法进行加权,使垃圾回收操作容易发生,或提早发生,或回收较多而已。

4)、finalize()方法

JVM垃圾收集器收集一个对象之前,一般要求程序调用适当的方法释放资源,但在没有明确释放资源的情况下,Java提供了默认机制来终止化该对象并释放资源,这个方法就是finalize(),即它是JVM在进行垃圾收集之前所做的一些清理工作,它的原型是protected void finalize() throws Throwable。

原创粉丝点击