`
zengjiaolong
  • 浏览: 7688 次
  • 性别: Icon_minigender_1
  • 来自: 宜昌
文章分类
社区版块
存档分类
最新评论

Java垃圾回收机制小结

阅读更多
一.谁在做Garbage Collection?

  一种流行的说法:在C++里,是系统在做垃圾回收;而在Java里,是Java自身在做。

  在C++里,释放内存是手动处理的,要用delete运算符来释放分配的内存。这是流行的说法。确切地说,是应用认为不需要某实体时,就需用delete 告诉系统,可以回收这块空间了。这个要求,对编码者来说,是件很麻烦、很难做到的事。随便上哪个BBS,在C/C++版块里总是有一大堆关于内存泄漏的话题。

  Java采用一种不同的,很方便的方法:Garbage Collection。垃圾回收机制放在JVM里。JVM完全负责垃圾回收事宜,应用只在需要时申请空间,而在抛弃对象时不必关心空间回收问题。

  二.对象在啥时被丢弃?

  在C++里,当对象离开其作用域时,该对象即被应用抛弃。

  在Java里,对象的生命期不再与其作用域有关,而仅仅与引用有关。

  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应用进程服务的,而不是为某个特定的进程服务的。因此,任何一个进程都不能命令垃圾回收机制做什么、怎么做或做多少。

  六.对象被回收时要做的事

  一个对象在运行时,可能会有一些东西与其关连。因此,当对象即将被销毁时,有时需要做一些善后工作。可以把这些操作写在finalize()方法(常称之为终止器)里。

  protected void finalize()

  {

  // finalization code here

  }

  这个终止器的用途类似于C++里的析构函数,而且都是自动调用的。但是,两者的调用时机不一样,使两者的表现行为有重大区别。C++的析构函数总是当对象离开作用域时被调用。这就是说,C++析构函数的调用时机是确定的,且是可被应用判知的。但是,Java终止器却是在对象被销毁时调用。一旦垃圾收集器准备好释放无用对象占用的存储空间,它首先调用那些对象的finalize()方法,然后才真正回收对象的内存。由上所知,被丢弃的对象何时被销毁,应用是无法获知的。而且,对于大多数场合,被丢弃对象在应用终止后仍未销毁。

  在编码时,考虑到这一点。譬如,某对象在运作时打开了某个文件,在对象被丢弃时不关闭它,而是把文件关闭语句写在终止器里。这样做对文件操作会造成问题。如果文件是独占打开的,则其它对象将无法访问这个文件。如果文件是共享打开的,则另一访问该文件的对象直至应用终结仍不能读到被丢弃对象写入该文件的新内容。

  至少对于文件操作,编码者应认清Java终止器与C++析构函数之间的差异。

  那么,当应用终止,会不会执行应用中的所有finalize()呢?据Bruce Eckel在Thinking in Java里的观点:“到程序结束的时候,并非所有收尾模块都会得到调用”。这还仅仅是指应用正常终止的场合,非正常终止呢?因此,哪些收尾操作可以放在 finalize()里,是需要酌酎的。

  七.Thinking ing java 一书中也对垃圾回收做了一些小结

  java垃圾回收,主要是靠一个低优先级的进程负责回收,注意,不是后台的进程

  他的优点是边回收,边调整堆使其紧凑

  主要有以下几种算法引用计数

  该算法在java虚拟机没被使用过,主要是循环引用问题,因为计数并不记录谁指向他,无法发现这些交互自引用对象。

  怎么计数?

  当引用连接到对象时,对象计数加1

  当引用离开作用域或被置为null时减1

  怎么回收?

  遍历对象列表,计数为0就释放

  有什么问题?

  循环引用问题。

  2.标记算法

  标记算法的思想是从堆栈和静态存储区的对象开始,遍历所有引用,标记活得对象

  对于标记后有两种处理方式

  (1)停止-复制

  所谓停止,就是停止在运行的程序,进行垃圾回收

  所谓复制,就是将活得对象复制到另外一个堆上,以使内存更紧凑

  优点在于,当大块内存释放时,有利于整个内存的重分配

  有什么问题?

  一、停止,干扰程序的正常运行,二,复制,明显耗费大量时间,三,如果程序比较稳定,垃圾比较少,那么每次重新复制量是非常大的,非常不合算

  什么时候启动停止-复制?

  内存数量较低时,具体多低我也不知道

  (2)清除

  也称标记-清除算法

  也就是将标记为非活得对象释放,也必须暂停程序运行

  优点就是在程序比较稳定,垃圾比较少的时候,速度比较快

  有什么问题?

  很显然停止程序运行是一个问题,只清除也会造成很对内存碎片。

  为什么这2个算法都要暂停程序运行?

  这是因为,如果不暂停,刚才的标记会被运行的程序弄乱,

  (3)分代收集

  分代收集是利用程序有大量临时对象的特点,对象每被引用一次,代数就增加,代数小的小型对象会被回收整理,大对象只会代数增加,不会被整理。

  优点在于对于处理大量临时的变量很有帮助

  (4)自适应

  jvm会监测垃圾回收的效率,在(1),(2)算法之间切换。

  3.增量收集,

  增量回收的主要算法还是分代(Young Objects 回收)与Train算法(Mature Object回收),所谓增量回收的关键问题是如何实现有序的增量回收而不会导致混乱(引用及其的增加与减少),分代可以逐代回收,Train算法可以逐个车厢回收,这样每次一代或每次一厢可以实现短停顿回收。
分享到:
评论
1 楼 jyjava 2011-12-28  
不错的文章,讲得很通俗易懂

相关推荐

    Java 垃圾回收小结(一)

    本文将对Java垃圾回收进行小结,探讨其基本原理、类型以及常见算法。 1. 基本原理: Java中的内存分为堆(Heap)和栈(Stack)两部分,垃圾回收主要关注堆内存。当一个对象不再被任何引用指向时,它被视为可回收的...

    Java个人学习小结

    - **垃圾回收机制**: Java 内置了垃圾回收机制,自动管理内存资源,避免了内存泄漏等问题。 #### Java 运行原理 Java 语言同时具备编译型和解释型的特点: - **编译过程**: `.java` 源文件通过 `javac.exe` 编译...

    JAVA IO流小结

    JAVA IO流小结 JAVA IO流是指Java语言中用来实现输入/输出操作的机制。IO流是指任何有能力产出数据的数据源对象或者有能力接收数据的数据源对象。他屏蔽了实际的I/O设备处理数据的细节。 一、流的定义和分类 流是...

    Java基础知识小结

    - **垃圾回收优化**:改进了垃圾回收机制,减少了暂停时间和内存占用。 - **并发性能提升**:增强了并发工具库,如`java.util.concurrent`包中的类,提高了多线程应用的性能。 - **文件I/O改进**:优化了文件读写...

    大话Java性能优化

    前言 第1章 性能调优策略概述 ...7.3 垃圾回收机制相关 7.4 实用JVM实验 7.5 本章小结 第8章 其他优化建议 8.1 Java现有机制及未来发展 8.2 系统架构优化建议 8.3 与编程无关 8.4 本章小结

    java基础小结

    - **自动内存管理**:Java使用垃圾回收机制(Garbage Collection)自动管理内存,程序员无需手动释放内存,降低了内存泄漏的风险。 - **异常处理**:Java通过try-catch-finally语句块进行异常处理,确保程序在遇到...

    关于static的小结(Java内存溢出)

    这意味着它们不受垃圾回收机制的影响,一旦分配则一直存在直到程序结束。如果程序中有大量的静态变量或者它们占用的空间很大,则可能引发方法区空间不足的问题,最终导致内存溢出。 2. **对象引用**:静态变量可以...

    java/c++区别

    2) **JAVA的新特性**:Java引入了垃圾回收机制,自动管理内存,简化了程序员的工作;并且提供了强类型检查和异常处理机制。 3) **两者共有的特性**:Java和C++都是面向对象的,都支持继承、封装和多态,但Java的实现...

    java个人总结,觉得还不错

    Java的垃圾回收机制主要包括以下几个方面: - **标记-清除算法**:最基础的垃圾回收算法,分为“标记”和“清除”两个阶段。 - **复制算法**:将内存分为大小相等的两块,每次只使用其中一块,在垃圾回收时将存活的...

    学习上的一些小结,主要是java和C#等

    在Java中,类是对象的蓝图,通过接口实现多继承,而异常处理和垃圾回收机制则提供了强大的错误处理和内存管理能力。 C#,由微软公司开发,主要用于.NET框架,同样是一种面向对象的语言,但更专注于Windows环境。C#...

    Java(J2SE、J2EE)学习小结

    7. 垃圾回收机制:Java的垃圾回收自动管理内存,避免了程序员手动释放内存的麻烦。优化GC包括减少内存消耗、合理使用引用类型、避免全局大对象等。 8. 浮点型精度:Java中的`float`型精度有限,不能精确表示3.4,...

    Java内存分配、管理小结.doc

    - 分配内存时,如果堆空间不足,会触发垃圾回收,清理不再使用的对象,释放空间。 4. **本地方法栈(Native Method Stack)**: - 本地方法栈与Java栈类似,但它是为Java虚拟机执行本地(非Java)方法服务的。 5...

    java笔试题小结

    ### Java笔试题小结 #### 1. Java 字符串(String) **问题**: String 类的特点是什么?与 StringBuffer 的区别? **分析与解答**: `String` 类在 Java 中是不可变的,即一旦创建了一个字符串对象,其内容就不能...

    毕向东Java笔记

    - **高性能**:通过JIT(Just-In-Time)编译器和先进的垃圾回收机制提高性能。 - **分布式**:Java内置对网络的支持,方便开发分布式应用。 - **动态性**:Java具有良好的动态性,能够适应不断变化的环境。 - **...

    Java咖啡馆.doc

    这部分将详细解释Java的概念,包括其设计原则、面向对象特性、垃圾回收机制以及JVM(Java虚拟机)的工作原理。Java是一种强类型、静态类型的编程语言,它的“一次编写,到处运行”特性使得程序能够在多种操作系统上...

    疯狂JAVA讲义

    1.7 垃圾回收机制 20 1.8 何时开始使用IDE工具 21 学生提问:老师,我想学习Java编程,到底是学习Eclipse好呢,还是学习JBuilder好呢? 21 1.9 本章小结 22 本章练习 22 第2章 理解面向对象 23 2.1 面向对象 ...

    java面试题目精选

    - **理解垃圾回收**:介绍了Java中的自动内存管理和垃圾回收机制。 - **初始器**:讲解了Java中用于初始化对象的构造函数和初始化块。 - **9.1 Java的多线程机制** - **进程与线程的区别**:解释了进程和线程的...

    Java面向对象教程

    理解内存分配和垃圾回收机制对于避免内存泄漏和提高程序性能至关重要。 6. 异常处理:Java提供了一套异常处理机制,通过try-catch-finally语句块来捕获和处理运行时错误。这有助于保持程序的健壮性,确保即使在发生...

Global site tag (gtag.js) - Google Analytics