深入JVM《四》 GC算法与种类

一、GC的概念

Garbage Collection 垃圾收集。

1960年 List 使用了GC。

Java中,GC的对象是堆空间和永久区。

二、
GC算法

1、
引用计数法(没有被java采用,在python中有)

老牌垃圾回收算法。

通过引用计算来回收垃圾。

引用计数器的实现很简单,对于一个对象A,只要有任何一个对象引用了A,则A的引用计数器就加1,当引用失效时,引用计数器就减1。只要对象A的引用计数器的值为0,则对象A就不可能再被使用。

问题:

1、引用和去引用伴随加法和减法,影响性能

2、很难处理循环引用,如果在根节点处以及不引用,但是子节点间互相引用,那么还是不能回收。

2、
标记清除

现代垃圾回收算法的思想基础。

标记-清除算法将垃圾回收分为两个阶段:标记阶段和清除阶段。

一种可行的实现是,在标记阶段,首先通过根节点,标记所有从根节点开始的可达对象。因此,未被标记的对象就是未被引用的垃圾对象。然后,在清除阶段,清除所有未被标记的对象。

3、标记压缩

标记-压缩算法适合用于存活对象较多的场合,如老年代。

它在标记-清除算法的基础上做了一些优化。和标记-清除算法一样,标记-压缩算法也首先需要从根节点开始,对所有可达对象做一次标记。但之后,它并不简单的清理未标记的对象,而是将所有的存活对象压缩到内存的一端。之后,清理边界外所有的空间。

4、复制算法

与标记-清除算法相比,复制算法是一种相对高效的回收方法

不适用于存活对象较多的场合 如老年代

将原有的内存空间分为两块,每次只使用其中一块,在垃圾回收时,将正在使用的内存中的存活对象复制到未使用的内存块中,之后,清除正在使用的内存块中的所有对象,交换两个内存的角色,完成垃圾回收

复制算法的最大问题是:空间浪费

我们整合标记清理思想来实现(分代GC算法):

在s0/s1区,每次复制回收都会让年龄加一。当到达某个年龄时,会认为是老年对象,直接从s区复制到老年代。

依据对象的存活周期进行分类,短命对象归为新生代,长命对象归为老年代。

根据不同代的特点,选取合适的收集算法:

    
少量对象存活【新生代】,适合复制算法
。(上图中的箭头都是复制算法)

    大量对象存活【老年代】,适合标记清理或者标记压缩
。(在老年代中使用)

三、可触及性

所有的算法,需要能够识别一个垃圾对象,因此需要给出一个可触及性的定义。

可触及性:

1、可触及的:从根节点可以触及到这个对象

2、可复活的

一旦所有引用被释放,就是可复活状态

因为在finalize()中可能复活该对象

3、不可触及的
(真正可以回收的对象):

在finalize()后,可能会进入不可触及状态

不可触及的对象不可能复活

可以回收

finalize()只会被调用一次。

package com.jvm.stack;

public class CanReliveObj {
    public static CanReliveObj obj;

    @Override
    protected void finalize() throws Throwable {
        super.finalize();
        System.out.println("CanReliveObj finalize called");
        obj = this;// 在这里让obj对象指向自己,也就是对象复合了。
    }

    @Override
    public String toString() {
        return "I am CanReliveObj";
    }

    public static void main(String[] args) throws
            InterruptedException {
        CanReliveObj obj = new CanReliveObj();
        obj = null;   //可复活
        System.gc();
        Thread.sleep(1000);
        if (obj == null) {
            System.out.println("obj 是 null");
        } else {
            System.out.println("obj 可用");
        }
        System.out.println("第二次gc");
        obj = null;    //不可复活
        System.gc();
        Thread.sleep(1000);
        if (obj == null) {
            System.out.println("obj 是 null");
        } else {
            System.out.println("obj 可用");
        }
    }
}
x

1

package com.jvm.stack;

2


3

public class CanReliveObj {

4

    public static CanReliveObj obj;

5


6

    @Override

7

    protected void finalize() throws Throwable {

8

        super.finalize();

9

        System.out.println("CanReliveObj finalize called");

10

        obj = this;// 在这里让obj对象指向自己,也就是对象复合了。

11

    }

12


13

    @Override

14

    public String toString() {

15

        return "I am CanReliveObj";

16

    }

17


18

    public static void main(String[] args) throws

19

            InterruptedException {

20

        CanReliveObj obj = new CanReliveObj();

21

        obj = null;   //可复活

22

        System.gc();

23

        Thread.sleep(1000);

24

        if (obj == null) {

25

            System.out.println("obj 是 null");

26

        } else {

27

            System.out.println("obj 可用");

28

        }

29

        System.out.println("第二次gc");

30

        obj = null;    //不可复活

31

        System.gc();

32

        Thread.sleep(1000);

33

        if (obj == null) {

34

            System.out.println("obj 是 null");

35

        } else {

36

            System.out.println("obj 可用");

37

        }

38

    }

39

}

40


经验:

避免使用finalize(),操作不慎可能导致错误。(如果第二次obj=null不设置,那么将导致obj不会被回收)

优先级低,何时被调用, 不确定

因为何时发生GC不确定

可以使用try-catch-finally来替代它

根的定义:

栈中引用的对象

方法区中静态成员或者常量引用的对象(全局对象)

JNI方法栈中引用对象

四、Stop-The-World

Java中一种全局暂停的现象。

全局停顿,所有Java代码停止,native代码可以执行,但不能和JVM交互。

多半由于GC引起

Dump线程

死锁检查

堆Dump

GC时为什么会有全局停顿?

类比在聚会时打扫房间,聚会时很乱,又有新的垃圾产生,房间永远打扫不干净。

只有让大家停止活动了,才能将房间打扫干净。

新生代的GC非常短。

老年代的GC有时候比较短,有时候很长。(有可能会几分钟设置几十分钟)

危害

长时间服务停止,没有响应

遇到HA系统,可能引起主备切换,严重危害生产环境。

原文地址:https://www.cnblogs.com/churao/p/8494172.html

时间: 2024-11-08 14:53:11

深入JVM《四》 GC算法与种类的相关文章

Java虚拟机详解----GC算法和种类

本文主要内容: GC的概念 GC算法  引用计数法(无法解决循环引用的问题,不被java采纳) 根搜索算法 现代虚拟机中的垃圾搜集算法: 标记-清除 复制算法(新生代) 标记-压缩(老年代) 分代收集 可触及性 Stop-The-World 一.GC的概念: GC:Garbage Collection 垃圾收集 1960年 Lisp使用了GC Java中,GC的对象是Java堆和方法区(即永久区) 我们接下来对上面的三句话进行一一的解释: (1)GC:Garbage Collection 垃圾收

JVM之GC算法

1. 前言 1.1 概念:清理内存中不会再被使用的对象 1.2 背景:如果内存中的垃圾不被清理,会导致内存溢出 1.3 常用的垃圾回收算法:引用计数法(Reference Counting).标记清除法(Mark-Sweep).复制算法(Copying).标记压缩法(Mark-Compact).分代算法(Generational Collecting)及分区算法(Region) 2. 算法演进 2.1 引用计数法[Java垃圾回收未采用] 2.1.1 思想:对于对象A,如果被引用,A的引用计数器

JVM的四种GC算法

程序在运行过程中,会产生大量的内存垃圾(一些没有引用指向的内存对象都属于内存垃圾,因为这些对象已经无法访问,程序用不了它们了,对程序而言它们已经死亡),为了确保程序运行时的性能,java虚拟机在程序运行的过程中不断地进行自动的垃圾回收(GC).关于 JVM 的 GC 算法主要有下面四种: 1.引用计数算法(Reference counting) 每个对象在创建的时候,就给这个对象绑定一个计数器.每当有一个引用指向该对象时,计数器加一:每当有一个指向它的引用被删除时,计数器减一.这样,当没有引用指

JVM之GC算法的实现(垃圾回收器)

上一节:<JVM之GC算法> 知道GC算法的理论基础,我们来看看具体的实现.只有落地的理论,才是真理. 一.JVM垃圾回收器的结构 JVM虚拟机规范对垃圾收集器应该如何实现没有规定,因为没有最好的垃圾收集器,只有最适合的场景. 图中展示了7种作用于不同分代的收集器,如果两个收集器之间存在连线,则说明它们可以搭配使用.虚拟机所处的区域则表示它是属于新生代还是老年代收集器. 7种:serial收集器.parnew收集器.parallel scavenge收集器.serial  old 收集器.pa

深入探究jvm之GC的算法及种类

一.GC基本概念 GC(Garbage Collection)垃圾收集,1960年最早在List中使用.在Java中GC回收的对象是堆空间和永久区,可以有效避免程序员人为造成内存泄漏问题.将堆空间和永久区没有作用的对象进行释放和回收. 二.GC算法 1.引用计数法: 是一种老牌的垃圾回收算法,通过引用计算来回收垃圾,被COM.ActionScript3.Python所使用. 引用计数法的实现很简单,对于一个对象A,只要有任何一个对象引用了A,那么A的引用计数器就会+1,当引用失效时,引用计数器就

JVM垃圾回收(四)- GC算法:实现(1)

GC算法:实现 上面我们介绍了GC算法中的核心概念,接下来我们看一下JVM里的具体实现.首先必须了解的一个重要的事实是:对于大部分的JVM来说,两种不同的GC算法是必须的,一个是清理Young Generation的算法,另一种是清理Old Generation的算法. 在JVM里有各种各样的这种内置算法,如果你没有特别指定GC算法,则会使用一个默认的.适应当前平台(platform-specific)的算法.接下来我们会解释每种算法的工作原理. 下面的列表提供了一个快速的预览,关于哪些算法可能

JVM学习(4)——全面总结Java的GC算法和回收机制---转载自http://www.cnblogs.com/kubixuesheng/p/5208647.html

俗话说,自己写的代码,6个月后也是别人的代码--复习!复习!复习!涉及到的知识点总结如下: 一些JVM的跟踪参数的设置 Java堆的分配参数 -Xmx 和 –Xms 应该保持一个什么关系,可以让系统的性能尽可能的好呢?是不是虚拟机内存越大越好? Java 7之前和Java 8的堆内存结构 Java栈的分配参数 GC算法思想介绍 –GC ROOT可达性算法 –标记清除 –标记压缩 –复制算法 可触及性含义和在Java中的体现 finalize方法理解 Java的强引用,软引用,弱引用,虚引用 GC

JVM系列(四) - JVM垃圾回收算法

前言 前面介绍了Java内存运行时区域,其中 程序计数器.虚拟机栈.本地方法栈 三个区域随线程而生,随线程而灭:栈中的栈帧随着方法的进入和退出而有条不紊地执行着出栈和入栈操作.每一个栈帧中分配多少内存基本上是在类结构确定下来时就已知的,因此这几个区域的内存分配和回收都具备确定性.在这几个区域内不需要过多考虑回收的问题,因为方法结束或线程结束时,内存自然就跟随着回收了. Java堆 和 方法区 则不一样,一个接口中的多个实现类需要的内存可能不一样,一个方法中的多个分支需要的内存也可能不一样.我们只

四种GC算法

四种GC算法 GC垃圾回收,首先需要判断哪些对象需要回收 判断对象存活 可达性分析: ? 从GC Roots开始向下查询,如果一个对象到任何一个GC Root对象都没有一个引用链相连的话,说明此对象不可用. ? 四个GC Root对象 JVM栈中引用的对象 方法区静态属性引用的对象 方法区中常量引用的对象 本地栈中JNI中引用的对象 四种GC算法 引用计数: ? 每个对象都有一个引用计数属性,多一个引用+1,少一个引用-1,为0的时候代表可以回收. ? 致命缺点:无法解决循环引用 复制算法: ?