3.垃圾搜集器以及垃圾收集算法

1.概述

  Java内存运行时区域的各个部分里:

  其中程序计数器、虚拟机栈、本地方法栈3各区域随线程而生,随线程而灭。栈中的栈帧随着方法的进入和退出而有条不紊地执行着出栈和入栈操作。每个栈帧中分配多少内存基本上是在类结构定下来是就已知了,因此这几个区域的内存分配和回收都具备确定性,不需过多考虑。

  而堆和方法区不一样,只有在程序处于运行期间才能你该知道创建哪些对象,这部分内存分配和回收是动态的,因此主要关注。

2.对象死亡判别

 1.引用计数法

    给对象中添加一个引用计数器,每当有一个地方引用时,计数器的值加1,;当引用失效时,计数器值减1,任何时刻计数器值为0的对象就是不会再被使用的对象。其实现简单,效率也较高,但是由于很难解决对象之间相互循环引用的问题。因此主流的Java虚拟机并没有这样来管理内存。

 2.可达性分析

    主流的实现都是可达性分析。基本思路就是通过一系列的称为“GC Roots”的对象作为起始点,从这些节点往下搜索,搜索所走过的路径称为引用链(Reference Chain),当一个对象到GC Roots没有任何引用链相连接,那么证明这个对象是不可用的。

    可作为GC Roots的对象包括以下几种:

    1.虚拟机栈(栈帧中的本地变量表)中引用的对象;

    2.方法区中静态属性引用的对象;

    3.方法去中场量引用的对象;

    4.本地方法栈中(即一般所说的Native方法)引用的对象。

      原因:GC管理的主要区域是Java堆,一般情况下只针对堆进行垃圾回收。方法区、栈和本地方法区不被GC所管理,因而选择这些区域内的对象作为    GC roots,被GC roots引用的对象不被GC回收。

    如果要细化GC Roots,GC Roots则包括:

      1,所有年老带对象

      2,所有全局对象
      3,所有jni句柄
      4,所有上锁对象
      5,jvmti持有的对象
      6,代码段code_cache
      7,所有classloader,及其加载的class
      8,所有字典
      9,flat_profiler和management
      10,最重要的,所有运行中线程栈上的引用类型变量。

 3.引用

    无论是引用计数法还是可达性分析,都谈的是“引用”,JDK1.2之前说Java的引用:如果reference类型的数据中存储的数值代表的是另一块内存的钱,就  成为这块内存代表着一个引用。因此JDK1.2后,将引用分为:强引用、软引用、弱引用、虚引用4种。

    强引用(Strong Reference):只要强引用还存在,垃圾搜集器永远不会回收被引用对象,如Object obj = new Object();

    软引用(Soft Reference):描述一些有用但非必须的对象,在系统将要发生内存溢出时就回收,JDK提供了SoftReference来实现软引用;

    弱引用(Weak Reference):用来描述非必须的对象,比软引用弱一些,被弱引用关联的对象只能生存到下次垃圾回收发生之前,垃圾回收发生时,不  论内存是否足够都会被回收,JDK提供了WeakReference来实现软引用;

    虚引用(Phantom Reference):也成幽灵引用或者幻影引用,最弱的引用关系。一个对象是否有虚引用的存在完全不会对其生存时间构成影响,也无  法通过虚引用来去的一个对象实例,对对象社只需饮用关联唯一用处就是能在这个对象被收集器回收时收到一个系统通知。JDK提供了PhantomReference     类来实现软引用; 

 4.生存死亡

    要宣布一个对象死亡至少要经历两次标记过程:如果通过可达性分析没有与GC Roots相连接的引用链,会被第一次标记和进行一次筛选。筛选条件是此  对象是否有执行finalize()方法,当对象没有覆盖finalize()方法,或者finalize()方法已经被虚拟机调用过。虚拟机将这两种情况都视为“没有必要执行”。

    如果一个对象有必要执行finalize()方法,会被放在F-Queue队列,并在稍后一个由虚拟机自己建立的、低优先级的Finalizer线程去执行它,虚拟机会触  发这个方法,但是不会等它执行完,否则如果一个对象在finalize()方法中执行缓慢,那么内存回收系统会崩溃。finalize()方法是对象最后一次逃脱死亡机   会。稍后GC将对F-Queue中的对象进行第二次小规模标记,如果对象在第二次标记前没能拯救自己就要被回收。拯救办法是只要与引用链上任何一个对象建  立关联即可。

  示例代码:

public class FinalizeEscapeGC {

    public static FinalizeEscapeGC SAVE_HOOK = null;

    public void isAlive(){
        System.out.println("yes,i am steal alive!");
    }

    protected void finalize() throws Throwable{
        super.finalize();
        System.out.println("finalize method executed.");
        FinalizeEscapeGC.SAVE_HOOK = this;
    }

    public static void main(String[] args) throws InterruptedException{
        SAVE_HOOK = new FinalizeEscapeGC();

        //对象第一次成功拯救自己
        SAVE_HOOK = null;
        System.gc();
        //因为finalize优先级很低,所以暂停0.5秒等待它
        Thread.sleep(500);
        if(SAVE_HOOK != null){
            SAVE_HOOK.isAlive();
        }else{
            System.out.println("no, i am dead.");
        }

        //下面这段代码与上面完全相同,却在自救中失败了
        SAVE_HOOK = null;
        System.gc();
        //因为finalize优先级很低,所以暂停0.5秒等待它
        Thread.sleep(500);
        if(SAVE_HOOK != null){
            SAVE_HOOK.isAlive();
        }else{
            System.out.println("no, i am dead.");
        }
    }

}

运行结果:

finalize method executed.
yes,i am steal alive!
no, i am dead.

  因为一个对象的finalize方法只会被系统自动调用一次,如果面临下一次回收,它的finalize()方法不会被再次执行,只有被回收。由于finalize()方法运行代价高昂,不确定性大,无法保证各个对象的调用顺序,因此不要使用。

 5.回收方法区

    虽然永久代的垃圾回收效率极低,但是也会回收,主要两部分内容:废弃常量呵呵无用的类。

  废弃常量的回收和堆中的对象类似,也是看是否有引用。

  无用的类的回收需要满足以下3个条件:

    1.该类所有的实例已被回收,也就是Java堆中不存在该类的任何实例;

    2.加载该类的ClassLoader已被回收;

    3.该类对应的java.lang.Class对象没有任何地方被引用,无法在任何地方通过反射访问该类的任何实例。

  即使满足条件也只是可被回收,并不像对象一定会被回收,是否对类进行回收虚拟机有自己的参数控制。

    在大量使用反射、动态代理、CGLib等ByteCode框架、动态生成JSP以及OSGi这类频繁自定义ClassLoader的场景都需要虚拟机具备自动卸载类的功     能,以保证永久代不会溢出。

时间: 2024-10-12 03:41:44

3.垃圾搜集器以及垃圾收集算法的相关文章

【JVM】JVM垃圾收集器、垃圾收集算法、无用对象

Java 常见的垃圾收集器有哪些 实际上,垃圾收集器(GC,Garbage Collector)是和具体 JVM 实现紧密相关的,不同厂商(IBM.Oracle),不同版本的JVM,提供的选择也不同.接下来,我来谈谈最主流的 Oracle JDK. Serial GC 它是最古老的垃圾收集器,"Serial"体现在其收集工作是单线程的,并且在进 行垃圾收集过程中,会进入臭名昭著的"Stop-The-World"状态.当然,其单线程设计也意味着精简的 GC 实现,无需

《深入理解JAVA虚拟机》JDK的垃圾收集算法

概念 垃圾收集是很多使用JAVA语言的IT从业者了解得比较少的地方. 但是涉及性能时非常重要.大公司面试除了算法,这部分也是会经常考察的地方. <深入理解JAVA虚拟机>一书中讲到JVM的垃圾收集算法和垃圾收集器. 垃圾收集算法分为: 1.标记清除算法 通常用在回收老年代内存. 最早的搜集算法就是标记清除(Mark-Sweep)算法了. 其原理是分为标记和清除两个阶段: 首先标记出所有需要回收的对象,在标记完成后统一回收所有被标记的对象. 主要不足两个: 一个是效率问题,标记过程和清除过程效率

JVM垃圾回收2(垃圾收集算法)

根据<深入理解java虚拟机>这本书总结 一.关于几个概念:(标记垃圾算法.垃圾收集算法.垃圾收集器) 前面说了如何寻找jvm垃圾,有两种方法:引用计数法/可达性算法.这篇准备讲,标记完垃圾之后,回收的算法,这里的算法只是垃圾回收的思想.后面会讲到多种垃圾收集器,这里的垃圾收集器就是运用了垃圾手机算法的思想,可以说是具体实现. 这里还是想多余的说一下这三个概念: 垃圾标记算法:标记垃圾的方法 垃圾收集算法:一种回收思想,供垃圾收集器使用.可能用在年轻代,也可能用在老年代(当然现在来说老年代和年

JVM(五)-垃圾收集算法和垃圾收集器

一.垃圾收集算法 (1)标记-清除算法 "标记-清除"(Mark-Sweep)算法,如它的名字一样,算法分为"标记"和"清除"两个阶段:首先标记出所有需要回收的对象,在标记完成后统一回收掉所有被标记的对象.之所以说它是最基础的收集算法,是因为后续的收集算法都是基于这种思路并对其缺点进行改进而得到的. 它的主要缺点有两个:一个是效率问题,标记和清除过程的效率都不高:另外一个是空间问题,标记清除之后会产生大量不连续的内存碎片,空间碎片太多可能会导致,

垃圾收集器与内存分配策略(二)之垃圾收集算法

垃圾收集器与内存分配策略(二)--垃圾收集算法 Java JVM 垃圾回收 简单了解算法的思想 1. 标记-清除算法 标记-清除算法分为标记和清除二个阶段:首先标记出需要回收的对象(详见上一节的可达性分析找出存活对象),在标记完成后统一回收所有被标记的对象. 缺点: 1.标记和清除二个过程的效率都不高 2.空间问题,标记清除后会产生大量不连续的内存碎片,空间碎片太多可能会导致以后再程序运行过程中需要分配较大对象时,无法找到足够的连续内存而不得不提前触发另一次垃圾收集动作. 2. 复制算法 复制算

J深入学习ava虚拟机之——垃圾收集算法与垃圾收集器

今天我们将一起学习Java虚拟机使用垃圾收集算法和常见的垃圾收集器.Java虚拟机内存区域的程序计数器.虚拟机栈和本地方法栈3个区域是随线程而生,随线程而灭:栈中的栈帧随着方法的进入和退出出栈和入栈.每一个栈帧中分配多少内存基本上是在类结构确定下来的时候就已知的,因此这个几个区域的内存分配和回收都具备确定性,在这几个区域就不需要过多考虑回收问题,因为方法结束或者线程结束时,内存自然就跟着回收了.而Java堆和方法区就不一样,一个接口中的多个类实现需要的内存可能不一样,一个方法中的多个分支需要的内

JVM理论:(二/3)垃圾收集算法、垃圾收集器

掌握三种垃圾算法,七种垃圾收集器,了解每种垃圾收集器使用的是哪种垃圾收集算法,以及关于SafePoint的知识点. 垃圾收集算法 1.标记-清除算法(Mark-Sweep) 先标记(如可达性算法)出所有需要回收的对象,标记完后再统一回收所有被标记的对象. 缺点:标记和清除过程的效率都不高,且清除后会产生大量不连续的内存碎片. 2.复制算法(Copying) 将可用内存划分为大小相等的两块,每次只使用其中的一块.当其中一块的内存用完了,就将还存活的对象复制到另一块内存上,然后再把已使用过的内存空间

JVM的垃圾回收机制 总结(垃圾收集、回收算法、垃圾回收器)

如果想了解Java内存模型参考:jvm内存模型-和内存分配以及jdk.jre.jvm是什么关系(阿里,美团,京东) 相信和小编一样的程序猿们在日常工作或面试当中经常会遇到JVM的垃圾回收问题,有没有在夜深人静的时候详细捋一捋JVM垃圾回收机制中的知识点呢?没时间捋也没关系,因为小编接下来会给你捋一捋. 一. 技术背景你要了解吧 二. 哪些内存需要回收? 2.1 引用计数算法 2.1.1 算法分析 2.1.2 优缺点 2.1.3 是不是很无趣,来段代码压压惊 2.2 可达性分析算法 2.3 Jav

Java 垃圾回收之新生代垃圾收集器

Stop-the-World JVM由于要执行GC而停止了应用程序的执行 任何一种GC算法中都会发生 多数GC优化通过减少Stop-the-world发生时间来提高程序性能 Safepoint  分析过程中对象引用关系不会发生变化的点 产生Safepoint的地方: 方法调用: 循环跳转: 异常跳转等 安全点数量得适中 JVM的运行模式 Server:启动较慢, Client: 启动较快 启动进入稳定期长期运行之后,Server的运行速度比Client快.因为Server采用重量级的虚拟机,对程