`
boy00fly
  • 浏览: 194871 次
  • 性别: Icon_minigender_1
  • 来自: 南京
社区版块
存档分类
最新评论

自己动手写写:Java GC

    博客分类:
  • JVM
阅读更多

为什么要使用垃圾收集器?

 

类似类型为什么要收集一样(参考http://boy00fly.iteye.com/blog/1108420)。java程序运行的过程中,越来越多的对象在堆中生成,占用的内存越来越大,如果不收集的话,到最后结果可想而知;即使堆内存足够,请求分配新对象时可能不得不增大堆空间的大小,虽然可以使用的总空闲空间是足够的,这是因为堆中没有连续的空闲空间放得下新的对象,在一个虚拟内存系统中,增长的堆所需的额外分页(或交换)空间会影响运行程序的性能。

 

使用垃圾收集器的优缺点

 

优点1. 可以提高生产率。

     程序员可以从复杂的释放内存空间的重担中解救出来。

 2. 保持程序的完整性

     垃圾收集是Java安全策略的一个重要部分,java程序员不可能因失误(或者故意)错误地释放内存而导致Java虚拟机崩溃。

 

缺点使用java垃圾收集堆,有一个潜在缺陷是它加大了程序负担,可能影响程序性能。因为Java虚拟机必须追踪哪些对象被正在执行的程序所引用,并且动态地终结并释放不再被使用的对象。和明确释放不再被使用的内存比起来,这个活动会需要更多的CPU时间。并且,在垃圾收集环境下,程序员对安排CPU时间来释放无用对象缺乏控制。

 

哪些对象是垃圾对象?

 

      首先要检测出垃圾对象。垃圾检测通常通过建立一个根对象的集合并且检查从这些根对象开始的可触及性来实现。如果正在执行的程序可以访问到的根对象和某个对象之间存在引用路径,这个对象就是可触及的。对于程序来说,根对象总是可以访问的。从这些根对象开始,任何可以被触及的对象都被认为是"活动"的对象。无法被触及的对象被认为是垃圾。

 

      下面来谈谈什么是根对象集合?

 

      Java虚拟机的根对象集合根据实现不同而不同,总体分为以下几个来源:

      1. 局部变量中的对象引用和栈帧的操作数栈(以及类变量中的对象引用)。这个总是包含的。

      2. 被加载的类的常量池中的对象引用,比如字符串。被加载的类的常量池可能指向保存在堆中的字符串,比如类名字、超类的名字、超接口的名字、字段名、字段特征签名、方法名或者方法特征签名。

      3. 传递到本地方法中的、没有被本地方法"释放"的对象引用。(本地方法接口,本地方法通过简单地返回释放引用,或者显示地调用一个回调函数来释放传递来的引用,或者是这两者的结合。)

      4. Java虚拟机运行时数据区中从垃圾收集器的堆中分配的部分。举例来说,在某些实现中,方法区中的类数据本身可能被存放在使用垃圾收集器的堆中,以便使用和释放对象。同样的垃圾收集算法来检测和卸载不再被引用的类。

 

      任何被根对象引用的对象都是可触及的,从而是活动的。另外,任何被活动的对象引用的对象都是可触及的。程序可以访问任何可触及的的对象,所以这些对象必须保留在堆里面。任何不可触及的对象都可以被收集,因为程序没有办法来访问他们。

 

       在Java虚拟机实现中,有些垃圾收集器可以区别真正的对象引用和看上去像合法对象引用的基本类型(比如一个int)之间的差别。(例如一个int整形,如果被解释是一个本地指针,可能指向堆中的一个对象)可是某些垃圾收集器仍然选择不区分真正的对象引用和"伪装品",这种垃圾收集器被称为保守的(conservative),因为他们可能不能总是释放一个不再被引用的对象。对保守的垃圾收集器,有时候垃圾对象也被错误地判断为活动的,因为有一个看上去像是对象引用的基本类型"引用"了对象。保守的收集器使垃圾收集速度提高了,因为有一些垃圾被遗忘了。

 

        区分活动对象和垃圾对象的两个基本方法是引用计数和跟踪。引用计数垃圾收集器通过为堆中的每个对象保存一个计数来区分活动对象和垃圾对象。这个计数记录下了对那个对象的引用次数。跟踪垃圾收集器实际上追踪从根节点开始的引用图。在追踪中遇上的对象以某种方式打上标记,当追踪结束时,没有被打上标记的对象就被判定是不可触及的,可以被当做垃圾收集。

 

垃圾收集算法

 

垃圾收集算法主要有以下几种

1、引用计数收集器

2、跟踪收集器

3、压缩收集器

4、拷贝收集器

5、按代收集的收集器

6、自适应收集器

7、火车算法(Sun公司的HotSpot虚拟机就是使用的此算法)

 

终结

 

在Java语言里面,一个对象可以拥有终结方法:这个方法是垃圾收集器在释放对象钱必须运行的。这个可能存在的终结方法使得任何Java虚拟机的垃圾收集器要完成的工作更加复杂。

给一个类加上终结方法,只需要简单地再类中声明一个方法:

 

class Example {
    
      protected void finalize() throws Throwable {
             //*****
             super.finalize();

      }
}

 

垃圾收集器必须检查他所发现的不再被引用的对象是否存在finalize()方法。

 

因为,存在终结方法时,Java虚拟机的垃圾收集器必须每次在收集时执行一些额外的步骤。首先,垃圾收集器必须使用某种方法检测出不再被引用的对象(称作第一遍扫描)。然后,它必须检查它检测出的不再被引用的对象是否声明了终结方法。如果时间允许的话,可能在这个时候垃圾收集过程就着手处理这些存在的终结方法。

 

当执行了所有的终结方法之后,垃圾收集器必须从根节点开始再次检测不再被引用的对象(称为第二遍扫描)。这个步骤是必要的,因为终结方法可能"复活"了某些不再被引用的对象,使他们再次被引用了。最后垃圾收集器才释放那些在第一次和第二次扫描中发现的都没有被引用的对象。

 

为了减少释放内存的时间,在扫描到某些对象拥有终结方法和运行这些终结方法之间,垃圾收集器可以有选择地插入一个步骤。一旦垃圾收集器执行了第一遍扫描,并且找到一些不再被引用的对象需要执行终结,他可以运行一次小型的跟踪,从需要执行终结的对象开始(而非从根节点开始)。任何满足如下条件的对象-------->从根节点开始不可触及(在第一遍扫描中检测出),以及从将要被终结的对象开始不可触及---------这些对象不可能在执行终结方法时复活,他们可以立即被是释放。

 

如果一个带有终结方法的对象不再被引用,并且他的终结方法运行过了,垃圾收集器必须使用某种方法记住这一点,而不能再次执行这个对象的终结方法。如果这个对象被它自己的终结方法或者其他对象的终结方法复活了,稍后再次不再被引用,垃圾收集器必须像对待一个没有终结方法的对象一样对待它。

 

使用Java编程时,必须记住一点:是垃圾收集器运行对象的终结方法。因为总是无法预测何时对象会被垃圾收集,所以也无法预测对象的终结方法何时运行。应该避免编写这样的程序,即程序的正确性依赖于对象的终结方法所运行的时机。比如,如果不再被引用的对象的终结方法释放了一个以后程序中将用到的资源,这个资源将直到垃圾收集器运行了这个对象的中终结方法后才能够使用。如果程序在垃圾收集器有机会终结这个不再被引用的对象之前需要这个资源,这个程序将无法得到该资源。

 

对象可触及性的生命周期

 

在版本1.2之前,在垃圾收集器来看,堆中的没一个对象都有三种状态之一:可触及的,可复活的,以及不可触及的。

可触及的,不可触及的这两种装载大家都清楚的。那什么状态才是”可复活的“?它在从根节点开始的追踪图中不可及,但是有可能在垃圾收集器执行某些终结方法时触及。所以说可复活状态的对象或许转化为可触及的状态,或者前进到不可触及状态。但是不可触及状态标志着不但对象不再被触及,而且也不可能通过任何终结方法复活,不可触及的对象不再对程序传递执行产生影响,可以自由地回收他们所占据的内存。

 

在后续版本中,上述三种状态扩充的新的状态,例如:在1.2版本中扩充了三个新状态:软可触及,弱可触及,以及影子可触及。这里就不再详述了。

 

 

以上内容参考《深入Java虚拟机》。

 

 

补充:以上讲的是对象的回收问题,大家有没有想过对象可以怎么创建?即类的实例化!

 以下4种是显式实例化的途径:

 1. 明确地使用new操作符

 2. 调用Class或者java.lang.reflect.COnstructor对象的newInstance()方法

 3. 调用任意对象的clone()方法

 4. 通过java.io.ObjectInputStream类的getObject()方法反序列化

 

         隐式实例化的途径:

 1. 保存命令行参数的String对象。(main函数的参数)

 2. Java虚拟机装载每一个类型,它会暗中实例化一个Class对象来代表这个类型。

 3. 执行包含字符串连接操作符的表达式产生对象。

 4. ........

 5. ........

 6. ........

 

2
1
分享到:
评论
1 楼 xjj2000 2012-05-21  
不错,支持!学习了!

相关推荐

    Tomcat内存溢出的解决方法(java.util.concurrent.ExecutionException)

    Tomcat内存溢出的解决方法(java.util.concurrent.ExecutionException:java.lang.OutOfMemoryError),内附解决方案!

    第6节: GC垃圾回收-02

    第6节: GC垃圾回收-02第6节: GC垃圾回收-02第6节: GC垃圾回收-02第6节: GC垃圾回收-02第6节: GC垃圾回收-02第6节: GC垃圾回收-02第6节: GC垃圾回收-02第6节: GC垃圾回收-02第6节: GC垃圾回收-02第6节: GC...

    记录java.lang.OutOfMemoryErrorJava heap space的情况.docx

    记录java.lang.OutOfMemoryError:Java heap space的情况 文章内容: 一.问题描述+原因分析+解决方案 二.JVM调优说明 三.Tomcat添加到jvisualvm监控

    JAVA gc日志分析工具GChisto及CMS GC补丁

    GChisto及CMS GC相应补丁文件,补丁文件未亲测。 This patch adds the following features and improvements when using CMS GC in incremental mode: detecting Full GCs corrected parsing errors when using -XX:...

    java GC手册

    GC java 手册 kindle格式 GC java 手册 kindle格式 GC java 手册 kindle格式

    Java Garbage Collection 与各种GC算法.zip

    面向对象:Java全面支持面向对象的特性,如封装、继承和多态,使得代码更易于维护和扩展。 安全:Java提供了丰富的安全特性,如禁止指针运算、自动内存管理和异常处理机制,以减少程序错误和恶意攻击的可能性。 ...

    VM调优实战指南:GC与性能优化

    Java虚拟机(JVM)是Java平台的核心组件,它负责将Java代码编译成字节码,并在运行时执行。在JVM的运行过程中,垃圾收集(GC)和性能调优是两个重要的方面。本文将详细介绍JVM的GC调优和性能调优方法,并通过具体...

    Java_GC垃圾回收调优指南

    让你对java gc 的工作原理有更深的了解 谢谢下载

    verbosegcanalyzer:Java GC日志汇总报告

    Verbose GC Analyzer是一个生成 CSV 导出和 Java GC 日志汇总报告的工具。 挖掘 Java GC 日志并生成: 总结报告 一个 HTML 报告,其中包含年轻规模、终身规模、提升规模、收集暂停时间和 CPU 挂机时间的图表 CSV ...

    Java GC的过程

    NULL 博文链接:https://wangwengcn.iteye.com/blog/1606192

    gcviewer_1.3.4_执行程序与示例

    java -jar gcviewer_1.3.4.jar gc.log 或者 java -jar gcviewer_1.3.4.jar gc.log summary.csv chart.png 其中; gc.log 是截取的一部分样本日志文件; 建议使用你自己的日志。 GCViewer官网: ...

    Java八股文的面试题

    垃圾回收(GC): Java通过垃圾回收机制自动管理内存,开发者无需手动释放对象占用的内存。常见的垃圾回收算法包括标记-清除、复制、标记-整理等。 Java集合框架(JCF): Java集合框架提供了一套性能优化的接口和类,...

    Java GC与性能调优

    Java GC与性能调优文档 作者:高飞

    Java基础[Java基础]--Java GC工作原理

    Java基础[Java基础]--Java GC工作原理

    java基础学习笔记 java整合技术 java工具类.rar

    健壮性:java的健壮性与自动垃圾回收机制有关,自动垃圾回收机制简称GC机制,java语言运行过程中产生的垃圾是自动回收的,不需要程序员关心。 可移植性:java程序可以做到一次编译,到处运行。在Windows操作系统上...

    java9源码下载-Java:java练习

    实现自己的类加载器:MyClassLoader.java 类加载测试:ClassLoaderCheck.java 显示加载测试:LoadDifference.java ByteCodeSample(字节码) 源文件:ByteCodeSample.java 字节码:ByteCodeSample.class DataSet...

    各大公司Java后端开发面试题总结.pdf

    内容概要:涵盖各大公司Java后端开发面试的常见考点,例如:Java内存模型、java GC、Synchronized 与Lock锁、java集合、线程池、Spring的IOC等等。帮助你系统复习并掌握核心知识。 适用人群:Java后端开发工程师、...

    团队合作:Java垃圾回收与各种GC算法

    团队合作:Java垃圾回收与各种GC算法

    java应用JVM的GC频率观察方法

    GC有两种类型:Scavenge GC(也称Young GC)和Full GC。 一般Full GC时,机器的Load会升高,应用也会停止响应一会(持续长达几秒),如果应用一直频繁的进行FullGC,一方面会出现应用无法提供正常服务,另一方面...

Global site tag (gtag.js) - Google Analytics