Java进阶之深入理解JVM(三)

深入理解JVM之GC

1.GC详解

1.GC 的作用域

在这里插入图片描述
口诀:关于垃圾回收:分代收集算法 不同的区域使用不同的算法

Young代: GC频繁区域

Old代:GC次数较少

Perm代:不会产生GC!

2. 一个对象的历程!

在这里插入图片描述

JVM在进行GC时,并非每次都是对三个区域进行扫描的!大部分的时候都是指的新生代!

3.GC两个类型:

  • 普通GC:只针对新生代 【GC】

  • 全局GC:主要是针对老年代,偶尔伴随新生代! 【Full GC】

4. GC 面试题

1、JVM内存模型,每个区中存放什么?

2、堆中的分区:Eden、S form to、老年代,请你说说他的特点?

3、GC的三种收集方法:标记清除、标记整理、复制算法,请你谈谈他的特点?

2.GC四大算法

1.引用计数法

在这里插入图片描述

特点:

  • 每个对象都有一个引用计数器,每当对象被引用一次,计数器就+1,如果引用失效,则计数器-1,如果为0,则GC可以清理;

缺点:

  • 计数器维护麻烦!
  • 循环引用无法处理!

JVM 一般不采用这种方式

现在一般使用可达性算法,GC Root…

2.复制算法

年轻代中,就是使用的复制算法!

在这里插入图片描述

1、一般普通GC 之后,差不多Eden几乎都是空的了!

2、每次存活的对象,都会被从 from 区和 Eden区等复制到 to区,from 和 to 会发生一次交换;记住一个点就好,谁空谁是to,每当幸存一次,就会导致这个对象的年龄+1;如果这个年龄值大于15(默认值,后面我们会讲解调整),就会进入养老区!

在这里插入图片描述

优点:

  • 没有标记和清除的过程!效率高!没有内存碎片!

缺点:

  • 需要浪费双倍的空间

Eden 区,对象存活率极低! 统计:99% 对象都会在使用一次之后,引用失效!推荐使用 复制算法

3.标记清除算法

老年代一般使用这个,但是会和我们后面的整理压缩一起使用!

在这里插入图片描述

优点:

  • 不需要额外的空间!

缺点:

  • 两次扫描,耗时较为严重,会产生内存碎片,不连续!

4.标记清除压缩!

在这里插入图片描述

减少了上面标记清除的缺点:没有内存碎片!但是耗时可能也较为严重!

那我们什么时候可以考虑使用这个算法呢?

在我们这个要使用算法的空间中,假设这个空间中很少,不经常发生GC,那么可以考虑使用这个算法!

5.GC算法小结

  • 内存效率:复制算法 > 标记清除算法 > 标记整理(时间复杂度!)

  • 内存整齐度:复制算法=标记整理>标记清除算法

  • 内存利用率:标记整理 = 标记清除算法 > 复制算法

从效率来说,复制算法最好,但是空间浪费较多!为了兼顾所有指标,标记整理会平滑一点,但是效率不尽人意!

难道就没有一种最优的算法吗?思考一下:

答案:没有!没有最好的,只有最合适的!=> 分代收集算法:不同的区域使用不同的算法!

年轻代:

相对于老年区,对象存活率低!

Eden 区,对象存活率极低! 统计:99% 对象都会在使用一次之后,引用失效!推荐使用 复制算法

老年代:

区域比较大,对象存活率较高!

推荐使用:标记清除压缩!

3.GC Roots(JVM 垃圾回收的时候如何确定垃圾)

什么是垃圾:简单地说,就是不在被引用的对象!

Person person = null;

如果我们要进行垃圾回收,第一步:判断这个对象是否可以回收!

1.引用计数法!

Java中,引用和对象都是有关联的,如果要操作对象,就要通过引用进行;

2.可达性分析算法!

在这里插入图片描述

一切都是从 GC Root 这个对象开始遍历的,只要在这里面的就不是垃圾!

3. 什么是Gc Root,(4种)

1、虚拟机栈中引用的对象!

2、类中静态属性引用的对象

3、方法区中的常量

4、本地方法栈中 Native 方法引用的对象!

public class GCRoots{
		
    // private byte[] array = new byte[100*1024*1024]; // 开辟内空间!
    // private static GCRoots2 t2; // GC root;
    // private static final GCRoots3 t3 = new GCRoots3(); // GC root;
    
    // 引用远远不止于此,强引用,软引用,弱引用,虚引用! 四个类的使用!
    public static void m1(){
        GCRoots g1 = new GCRoots(); //GCroot
        System.gc();
    }
    
    public static void main(String[] args){
        m1();
    }

}

4.GC回收日志详解

1.GC回收触发代码

package com.coding.oom;

import java.util.Random;

/*
 * -Xmx8m -Xms8m -XX:+PrintGCDetails
 * GC :串行执行 STW(Stop The World)  并行执行   G1
*/

public class Demo02 {
    public static void main(String[] args) {
        System.gc(); // 手动唤醒GC(),等待cpu的调用
        String str = "ilovecoding";
        while (true){
            str += str
                    + new Random().nextInt(999999999)
                    + new Random().nextInt(999999999);
        }
        // 出现问题:java.lang.OutOfMemoryError: Java heap space
    }
}

2.GC日志详情分析

[GC (System.gc()) [PSYoungGen: 615K->496K(2048K)] 835K->740K(7680K), 0.0010787 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
[Full GC (System.gc()) [PSYoungGen: 496K->0K(2048K)] [ParOldGen: 244K->622K(5632K)] 740K->622K(7680K), [Metaspace: 3141K->3141K(1056768K)], 0.0061742 secs] [Times: user=0.00 sys=0.00, real=0.01 secs] 

* 分析GC日志:
 *
 *  [Times: user=0.00 sys=0.00, real=0.00 secs]
 * 1、GC 类型  GC:普通的GC,Full GC :重GC
 * 21536K 执行 GC之前的大小
 * 3504K  执行 GC之后的大小
 * 4(2048K) young 的total大小
 * 50.0012643 secs 清理的时间
 * 6、user 总计GC所占用CPU的时间   sys OS调用等待的时间   real 应用暂停的时间
 *
 * GC :串行执行 STW(Stop The World)  并行执行   G1
*/
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值