JVM从入门到精通

查看JVM常用命令

  1. 查看GC信息
jstat -gcutil <pid> 1000

jinfo

 jstat -gc <pid> 1000

在这里插入图片描述

  1. java和jvm的配置信息
jinfo <pid> 

在这里插入图片描述
在这里插入图片描述

cpu使用率

top -p <pid>

在这里插入图片描述

课程结构
在这里插入图片描述

尚硅谷_宋红康_JVM从入门到精通: https://www.bilibili.com/video/BV1PJ411n7xZ?from=search&seid=12508719405042682431

参考笔记连接:
https://blog.csdn.net/weixin_45759791/category_10123040.html

jvm(java虚拟机):一次编译到处运行,自动的管理内存,自动垃圾回收,降低内存泄漏的概率

建议书籍:

在这里插入图片描述

一. JVM内存与垃圾回收篇概述

P2 02-如何看待Java上层技术与JVM
P3 03-为什么要学习JVM
P4 04-面向人群和课程特点

P5 05-官方规范下载与参考书目

在这里插入图片描述

P6 06-跨平台的语言Java和跨语言的平台JVM(java虚拟机)

java 因为有jvm 成了跨平台的语言
jvm(java虚拟机): 一个抽象的计算机
在这里插入图片描述

除了java以外可以使用jvm(java虚拟机)
jvm : 跨语言的平台
在这里插入图片描述

在这里插入图片描述

P7 07-字节码与多语言混合编程

  • 字节码:
    在这里插入图片描述
  • 多语言混合编程:
    在这里插入图片描述

P8 08-Java及JVM历史上的重大事件

在这里插入图片描述

P9 09-虚拟机与Java虚拟机介绍

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

P10 10-JVM的位置

  • JVM的位置:
    在这里插入图片描述

P11 11-JVM的整体结构

  • JVM的整体结构
    在这里插入图片描述
    更详细的图
    在这里插入图片描述

P12 12-Java代码执行流程

  • Java代码执行流程
    在这里插入图片描述

P13 13-区分栈的指令集架构和寄存器的指令集架构

在这里插入图片描述

P14 14-JVM的生命周期

  • JVM的生命周期![在这里插入图片描述
    在这里插入图片描述

P15 15-SUN Classic VM的介绍
P16 16-Exact VM的介绍

P17 17-HotSpot VM的介绍

在这里插入图片描述

P18 18-JRockit VM的介绍
P19 19-IBM J9 VM的介绍
P20 20-KVM、CDC、CLDC的介绍
P21 21-Azul VM和BEA Liquid VM的介绍
P22 22-Apache Harmony的介绍
P23 23-Microsoft JVM和TaobaoJVM
P24 24-Dalvik VM及其他虚拟机的介绍
P25 25-Graal VM的介绍

P26 26-内存结构概述

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

类加载子系统

P27 27-概述类的加载器及类加载过程

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

P28 28-类的加载过程一:Loading

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

P29 29-类的加载过程二:Linking

在这里插入图片描述
在这里插入图片描述

P30 30-类的加载过程三:Initialization
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

P31 31-几种类加载器的使用体会

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

P32 32-引导类、扩展类、系统类加载器的使用及演示

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

P33 33-为什么需要用户自定义类加载器及具体实现

在这里插入图片描述
P34 34-ClassLoader的常用方法及获取方法
P35 35-双亲委派机制的工作原理及演示
P36 36-双亲委派机制的优势
P37 37-沙箱安全机制
P38 38-类的主动使用与被动使用等

运行时数据区

运行时数据区常见面试题
百度
三面:说一下JVM内存模型吧,有哪些区?分别干什么的?

蚂蚁金服:
Java8的内存分代改进
JVM内存分哪几个区,每个区的作用是什么?
一面:JVM内存分布/内存结构?栈和堆的区别?堆的结构?为什么两个survivor区?
二面:Eden和survior的比例分配

小米:
jvm内存分区,为什么要有新生代和老年代

字节跳动:
二面:Java的内存分区
二面:讲讲vm运行时数据库区
什么时候对象会进入老年代?

京东:
JVM的内存结构,Eden和Survivor比例。
JVM内存为什么要分成新生代,老年代,持久代。新生代中为什么要分为Eden和survivor。

天猫:
一面:Jvm内存模型以及分区,需要详细到每个区放什么。
一面:JVM的内存模型,Java8做了什么改

拼多多:
JVM内存分哪几个区,每个区的作用是什么?

美团:
java内存分配
jvm的永久代中会发生垃圾回收吗?
一面:jvm内存分区,为什么要有新生代和老年代?

视频链接:https://www.bilibili.com/video/BV1PJ411n7xZ
三面:说一下JVM内存模型吧,有哪些区?分别干什么的?

蚂蚁金服:
Java8的内存分代改进
JVM内存分哪几个区,每个区的作用是什么?
一面:JVM内存分布/内存结构?栈和堆的区别?堆的结构?为什么两个survivor区?
二面:Eden和survior的比例分配

小米:
jvm内存分区,为什么要有新生代和老年代

字节跳动:
二面:Java的内存分区
二面:讲讲vm运行时数据库区
什么时候对象会进入老年代?

京东:
JVM的内存结构,Eden和Survivor比例。
JVM内存为什么要分成新生代,老年代,持久代。新生代中为什么要分为Eden和survivor。

天猫:
一面:Jvm内存模型以及分区,需要详细到每个区放什么。
一面:JVM的内存模型,Java8做了什么改

拼多多:
JVM内存分哪几个区,每个区的作用是什么?

美团:
java内存分配
jvm的永久代中会发生垃圾回收吗?
一面:jvm内存分区,为什么要有新生代和老年代?

在这里插入图片描述

P39 39-运行时数据区内部结构

在这里插入图片描述

  • 运行时数据区内部结构:

jdk1.8后方法区叫元数据区(元空间)
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

P40 40-JVM中的线程说明

在这里插入图片描述
在这里插入图片描述

P41 41-PC寄存器概述

  • PC寄存器的作用:

PC寄存器用于存储下一条要执行代码的地址,及PC寄存器指向下一条要执行的代码

pc寄存器没有GC(垃圾回收),也不会出现内存溢出

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

P42 42-PC寄存器的使用举例

P43 43-解决PC寄存器两个面试问题

在这里插入图片描述

在这里插入图片描述

第五章、虚拟机栈—栈 (重要)

P44 44-java虚拟机栈

栈不存在GC(垃圾回收)

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

P45 45-虚拟机栈的常见异常与如何设置栈大小

在这里插入图片描述
递归自己调自己的方法,在递归没有结束时一直不释放栈内存,如果递归很深,容易出现栈溢出/内存泄漏
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

P46 46-栈的存储结构和运行原理

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

P47 47-栈桢的内部结构

在这里插入图片描述

P48 48-局部变量表结构的认识

在这里插入图片描述
在这里插入图片描述

P49 49-字节码中方法内部结构的剖析
P50 50-变量槽slot的理解与演示
P51 51-静态变量与局部变量的对比及小结
P52 52-操作数栈的特点
P53 53-涉及操作数栈的字节码指令执行分析
P54 54-栈顶缓存技术

P55 55-动态链接的理解与常量池的作用

在这里插入图片描述

为什么需要运行时常量池?

因为在不同的方法,都可能调用常量或者方法,所以只需要存储一份即可,节省了空间

常量池的作用:就是为了提供一些符号和常量,便于指令的识别

P56 56-方法的绑定机制:静态绑定与动态绑定

P57 57-4种方法调用指令区分非虚方法与虚方法

在这里插入图片描述

在这里插入图片描述

P58 58-invokedynamic指令的使用

P59 59-方法重写的本质与虚方法表的使用

在这里插入图片描述
在这里插入图片描述
如下图所示:如果类中重写了方法,那么调用的时候,就会直接在虚方法表中查找,否则将会直接连接到Object的方法中。
在这里插入图片描述

P60 60-方法返回地址的说明
P61 61-栈桢中的一些附加信息

P62 62-虚拟机栈的5道面试题

在这里插入图片描述

栈的相关面试题

  1. 举例栈溢出的情况?(StackOverflowError)
    通过 -Xss设置栈的大小, 递归深度很深,或者递归出现死循环

  2. 调整栈大小,就能保证不出现溢出么?
    不能保证不溢出, 递归深度很深,或者递归出现死循环

  3. 分配的栈内存越大越好么?
    不是,一定时间内降低了OOM(内存溢出)概率,但是会挤占其它的线程空间,因为整个空间是有限的。

  4. 垃圾回收是否涉及到虚拟机栈?
    不会

  5. 运行时数据区,是否存在Error和GC?

在这里插入图片描述

  1. 方法中定义的局部变量是否线程安全?
    具体问题具体分析
    何为线程安全?
  • 如果只有一个线程才可以操作此数据,则必是线程安全的
  • 如果有多个线程操作,则此数据是共享数据(由外部传入的参数,或内部参数返回,参数的作用域不止在方法内部),如果不考虑共享机制,则为线程不安全
    总结一句话就是:如果对象是在内部产生,并在内部消亡,没有返回到外部,那么它就是线程安全的,反之则是线程不安全的。
/**
 * 面试题
 * 方法中定义局部变量是否线程安全?具体情况具体分析
 * 何为线程安全?
 *    如果只有一个线程才可以操作此数据,则必是线程安全的
 *    如果有多个线程操作,则此数据是共享数据,如果不考虑共享机制,则为线程不安全
 * @author: 陌溪
 * @create: 2020-07-06-16:08
 */
public class StringBuilderTest {

    // s1的声明方式是线程安全的,因为是内部产生,内部消亡的
    public static void method01() {
        // 线程内部创建的,属于局部变量
        StringBuilder s1 = new StringBuilder();
        s1.append("a");
        s1.append("b");
    }

    // 这个也是线程不安全的,因为有返回值,有可能被其它的程序所调用
    public static StringBuilder method04() {
        StringBuilder stringBuilder = new StringBuilder();
        stringBuilder.append("a");
        stringBuilder.append("b");
        return stringBuilder;
    }

    // stringBuilder 是线程不安全的,操作的是共享数据
    public static void method02(StringBuilder stringBuilder) {
        stringBuilder.append("a");
        stringBuilder.append("b");
    }


    /**
     * 同时并发的执行,会出现线程不安全的问题
     */
    public static void method03() {
        StringBuilder stringBuilder = new StringBuilder();
        new Thread(() -> {
            stringBuilder.append("a");
            stringBuilder.append("b");
        }, "t1").start();

        method02(stringBuilder);
    }

    // StringBuilder是线程安全的,但是String也可能线程不安全的,以为返回的是String,可能被其他线程调用
    public static String method05() {
        StringBuilder stringBuilder = new StringBuilder();
        stringBuilder.append("a");
        stringBuilder.append("b");
        return stringBuilder.toString();
    }
}

第六章、本地方法接口

尚硅谷JVM从入门到精通宋红康版|第六章、本地方法接口

P63 63-本地方法接口的理解(先跳出运行数据区讲一下本地方法库)

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

P64 64-本地方法栈的理解

在这里插入图片描述
在这里插入图片描述

P65 65-JVM学习路线与内容回顾

第八章、堆(运行时数据区最重要的)

尚硅谷JVM从入门到精通宋红康版|第八章、堆

P66 66-堆空间的概述_进程中堆的唯一性

堆的核心概念

堆针对一个JVM进程来说是唯一的,也就是一个进程只有一个JVM,但是进程包含多个线程,他们是共享同一堆空间的。

一个java 程序运行起来就是一个进程,一个进程对应一个jvm实例,一个jvm实例对应一个运行时数据区,一个运行时数据去对应一个堆和方法区

一个进程包的所有线程是共享同一堆空间和方法区的,每个线程有自己独立的栈、程序计数器、本地方法栈。
在这里插入图片描述
在这里插入图片描述
idea设置java程序运行时堆大小

-Xms
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

运行HeaoDemo java程序

查看运行的堆空间使用情况
下图就是使用:Java VisualVM查看堆空间的内容,通过 jdk bin提供的插件

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

P67 67-堆空间关于对象创建和和GC的概述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

P68 68-堆的细分内存结构

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

P69 69-堆空间大小的设置和查看

在这里插入图片描述
在这里插入图片描述

  • -Xms 用来设置堆空间(年轻代+老年代)的初始内存大小
  • -X:是jvm运行参数
  • ms:memory start
  • -Xmx:用来设置堆空间(年轻代+老年代)的最大内存大小
/**
 * -Xms 用来设置堆空间(年轻代+老年代)的初始内存大小
 *  -X:是jvm运行参数
 *  ms:memory start
 * -Xmx:用来设置堆空间(年轻代+老年代)的最大内存大小
 *
 * @author: 陌溪
 * @create: 2020-07-06-20:44
 */
public class HeapSpaceInitial {
    public static void main(String[] args) {
        // 返回Java虚拟机中的堆内存总量
        long initialMemory = Runtime.getRuntime().totalMemory() / 1024 / 1024;
        // 返回Java虚拟机试图使用的最大堆内存
        long maxMemory = Runtime.getRuntime().maxMemory() / 1024 / 1024;
        System.out.println("-Xms:" + initialMemory + "M");
        System.out.println("-Xmx:" + maxMemory + "M");
    }
}

在这里插入图片描述

手动设置堆内存
在这里插入图片描述
如何查看堆内存的内存分配情况:

方式一:

先查看当前程序运行进程
在这里插入图片描述

看某个进程内存分配信息:

jps  ->  staat -gc  进程id

在这里插入图片描述
25600+153600+409600=588800/1024=575

25600+25600+153600+409600=614400/1024=600

因为存储的时候s0c和s1c都能放,但有一个始终是空的,所以我们打印的是575(有一个没算),而我们查询内存分配总的是600

方式二:
在这里插入图片描述

即打印gc细节

-XX:+PrintGCDetails

在程序运行结束后打印
在这里插入图片描述

P70 70-OOM的说明与举例

设置堆内存:
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

old区已满溢出

我们简单的写一个OOM例子

/**
 * OOM测试
 *
 * @author: 陌溪
 * @create: 2020-07-06-21:11
 */
public class OOMTest {
    public static void main(String[] args) {
        List<Integer> list = new ArrayList<>();
        while(true) {
            list.add(999999999);
        }
    }
}

然后设置启动参数
设置堆内存:

-Xms10m -Xmx:10m

1

运行后,就出现OOM了,那么我们可以通过 VisualVM这个工具查看具体是什么参数造成的OOM

P71 71-新生代与老年代中相关参数的设置

在这里插入图片描述
在这里插入图片描述

P72 72-图解对象分配的一般过程

s0和s1谁为空时谁为to
伊甸园(Eden)(《圣经》中亚当和夏娃最初居住的地方)

伊甸园区(Eden)满时触发MinorGC

我们创建的对象,一般都是存放在Eden区的,当我们Eden区满了后,就会触发GC操作,一般被称为 YGC / Minor GC操作

在这里插入图片描述
当我们进行一次垃圾收集后,红色的将会被回收,而绿色的还会被占用着,存放在S0(Survivor From)区。同时我们给每个对象设置了一个年龄计数器,一次回收后就是1。

同时Eden区继续存放对象,当Eden区再次存满的时候,又会触发一个MinorGC操作,此时GC将会把 Eden和Survivor From中的对象 进行一次收集,把存活的对象放到 Survivor To区,同时让年龄 + 1
在这里插入图片描述
我们继续不断的进行对象生成 和 垃圾回收,当Survivor中的对象的年龄达到15的时候,将会触发一次 Promotion晋升的操作,也就是将年轻代中的对象 晋升到 老年代中
在这里插入图片描述

在这里插入图片描述
思考:幸存区区满了后?
特别注意,在Eden区满了的时候,才会触发MinorGC,而幸存者区满了后,不会触发MinorGC操作

如果Survivor区满了后,将会触发一些特殊的规则,也就是可能直接晋升老年代
在这里插入图片描述
一般情况下大部分的对象在Eden区就被MinorGC回收了

P73 73-对象分配的特殊情况、

在这里插入图片描述

P74 74-代码举例与JVisualVM演示对象的分配过程

/**
 * 代码演示对象创建过程
 *
 * @author: 陌溪
 * @create: 2020-07-07-9:16
 */
public class HeapInstanceTest {
    byte [] buffer = new byte[new Random().nextInt(1024 * 200)];
    public static void main(String[] args) throws InterruptedException {
        ArrayList<HeapInstanceTest> list = new ArrayList<>();
        while (true) {
            list.add(new HeapInstanceTest());
            Thread.sleep(10);
        }
    }
}

然后设置JVM参数

-Xms600m -Xmx600m

最终,在老年代和新生代都满了,就出现OOM
在这里插入图片描述

然后cmd输入下面命令,打开VisualVM图形化界面

jvisualvm

然后通过执行上面代码,通过VisualGC进行动态化查看

在这里插入图片描述

P75 75-常用优工具概述与Jprofiler的演示

常用的调优工具

  • JDK命令行
  • Eclipse:Memory Analyzer Tool
  • Jconsole
  • Visual VM(实时监控 推荐~)
  • Jprofiler(推荐~)
  • Java Flight Recorder(实时监控)
  • GCViewer
  • GCEasy
    在这里插入图片描述

P76 76-MinorGC、MajorGC和FullGC的对比

  • Minor GC:新生代的GC
  • Major GC:老年代的GC
  • Full GC:整堆收集,收集整个Java堆和方法区的垃圾收集

我们都知道,JVM的调优的一个环节,也就是垃圾收集,我们需要尽量的避免垃圾回收,因为在垃圾回收的过程中,容易出现STW的问题
而 Major GC 和 Full GC出现STW的时间,是Minor GC的10倍以上,Minor GC会引发STW。
所有jvm调优主要避免GC,调优主要是针对Major GC 和 Full GC

STW: 在进行垃圾回收的时候要暂停其它用户的线程,等垃圾回收结束,用户线程才恢复运行,会造成一段时间用户线程不可用。
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

P77 77-GC举例与日志分析

我们编写一个OOM的异常,因为我们在不断的创建字符串,是存放在元空间的

/**
 * GC测试
 *
 * @author: 陌溪
 * @create: 2020-07-07-10:01
 */
public class GCTest {
    public static void main(String[] args) {
        int i = 0;
        try {
            List<String> list = new ArrayList<>();
            String a = "mogu blog";
            while(true) {
                list.add(a);
                a = a + a;
                i++; 
            }
        }catch (Exception e) {
            e.getStackTrace();
        }
    }
}

设置JVM启动参数

-Xms10m -Xmx10m -XX:+PrintGCDetails

打印出的日志
在这里插入图片描述

[GC (Allocation Failure) [PSYoungGen: 2038K->500K(2560K)] 2038K->797K(9728K), 0.3532002 secs] [Times: user=0.01 sys=0.00, real=0.36 secs] 
[GC (Allocation Failure) [PSYoungGen: 2108K->480K(2560K)] 2405K->1565K(9728K), 0.0014069 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
[Full GC (Ergonomics) [PSYoungGen: 2288K->0K(2560K)] [ParOldGen: 6845K->5281K(7168K)] 9133K->5281K(9728K), [Metaspace: 3482K->3482K(1056768K)], 0.0058675 secs] [Times: user=0.00 sys=0.00, real=0.01 secs] 
[GC (Allocation Failure) [PSYoungGen: 0K->0K(2560K)] 5281K->5281K(9728K), 0.0002857 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
[Full GC (Allocation Failure) [PSYoungGen: 0K->0K(2560K)] [ParOldGen: 5281K->5263K(7168K)] 5281K->5263K(9728K), [Metaspace: 3482K->3482K(1056768K)], 0.0058564 secs] [Times: user=0.00 sys=0.00, real=0.01 secs] 
Heap
 PSYoungGen      total 2560K, used 60K [0x00000000ffd00000, 0x0000000100000000, 0x0000000100000000)
  eden space 2048K, 2% used [0x00000000ffd00000,0x00000000ffd0f138,0x00000000fff00000)
  from space 512K, 0% used [0x00000000fff00000,0x00000000fff00000,0x00000000fff80000)
  to   space 512K, 0% used [0x00000000fff80000,0x00000000fff80000,0x0000000100000000)
 ParOldGen       total 7168K, used 5263K [0x00000000ff600000, 0x00000000ffd00000, 0x00000000ffd00000)
  object space 7168K, 73% used [0x00000000ff600000,0x00000000ffb23cf0,0x00000000ffd00000)
 Metaspace       used 3514K, capacity 4498K, committed 4864K, reserved 1056768K
  class space    used 388K, capacity 390K, committed 512K, reserved 1048576K
  
  Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
	at java.util.Arrays.copyOfRange(Arrays.java:3664)
	at java.lang.String.<init>(String.java:207)
	at java.lang.StringBuilder.toString(StringBuilder.java:407)
	at com.atguigu.java.chapter08.GCTest.main(GCTest.java:20)

P78 78-体会堆空间分代的思想

在这里插入图片描述
在这里插入图片描述

P79 79-总结堆内存分配策略

在这里插入图片描述
在这里插入图片描述
大对象直接到老年区举例:
在这里插入图片描述
在这里插入图片描述

P80 80-堆空间为每个线程分配的TLAB

问题:堆空间都是共享的么?

不一定,因为还有TLAB这个概念,在堆中划分出一块区域,为每个线程所独占

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
查看tlab是否开启
在这里插入图片描述
对于单个线程TLAB分配过程:
对象首先是通过TLAB开辟空间,如果不能放入,那么需要通过Eden来进行分配
在这里插入图片描述

P81 81-小结堆空间的常用参数设置(面试常问,查看你是否在实际项目中使用过)

jvm堆空间常用参数:

官网:https://docs.oracle.com/javase/8/docs/technotes/tools/unix/java.html
在这里插入图片描述
在这里插入图片描述

在发生Minor GC之前,虚拟机会检查老年代最大可用的连续空间是否大于新生代所有对象的总空间:
在这里插入图片描述

P82 82-通过逃逸分析看堆空间的对象分配策略

逃逸分析:对象的使用作用域是否超出一个方法。
如果对象的使用作用域只在一个方法内,就可以把此对象分配到堆上。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
完整的逃逸分析代码举例

/**
 * 逃逸分析
 * 如何快速的判断是否发生了逃逸分析,大家就看new的对象是否在方法外被调用。
 * @author: 陌溪
 * @create: 2020-07-07-20:05
 */
public class EscapeAnalysis {

    public EscapeAnalysis obj;

    /**
     * 方法返回EscapeAnalysis对象,发生逃逸
     * @return
     */
    public EscapeAnalysis getInstance() {
        return obj == null ? new EscapeAnalysis():obj;
    }

    /**
     * 为成员属性赋值,发生逃逸
     */
    public void setObj() {
        this.obj = new EscapeAnalysis();
    }

    /**
     * 对象的作用于仅在当前方法中有效,没有发生逃逸
     */
    public void useEscapeAnalysis() {
        EscapeAnalysis e = new EscapeAnalysis();
    }

    /**
     * 引用成员变量的值,发生逃逸
     */
    public void useEscapeAnalysis2() {
        EscapeAnalysis e = getInstance();
        // getInstance().XXX  发生逃逸
    }
}

在这里插入图片描述
在这里插入图片描述

P83 83-代码优化之栈上分配

在这里插入图片描述
**栈上分配: **
在这里插入图片描述
举例
我们通过举例来说明 开启逃逸分析 和 未开启逃逸分析时候的情况

/**
 * 栈上分配
 * -Xmx1G -Xms1G -XX:-DoEscapeAnalysis -XX:+PrintGCDetails
 * @author: 陌溪
 * @create: 2020-07-07-20:23
 */
class User {
    private String name;
    private String age;
    private String gender;
    private String phone;
}
public class StackAllocation {
    public static void main(String[] args) throws InterruptedException {
        long start = System.currentTimeMillis();
        for (int i = 0; i < 100000000; i++) {
            alloc();
        }
        long end = System.currentTimeMillis();
        System.out.println("花费的时间为:" + (end - start) + " ms");

        // 为了方便查看堆内存中对象个数,线程sleep
        Thread.sleep(10000000);
    }

    private static void alloc() {
        User user = new User();
    }
}

设置JVM参数,表示未开启逃逸分析

-XX:-DoEscapeAnalysis 关闭逃逸分析

-Xmx1G -Xms1G -XX:-DoEscapeAnalysis -XX:+PrintGCDetails

运行结果,同时还触发了GC操作

花费的时间为:664 ms

在这里插入图片描述
我们在开启逃逸分析(-号改成+号:开启逃逸分析)

-XX:+DoEscapeAnalysis 开启逃逸分析

-Xmx1G -Xms1G -XX:+DoEscapeAnalysis -XX:+PrintGCDetails

然后查看运行时间,我们能够发现花费的时间快速减少,同时不会发生GC操作

花费的时间为:5 ms

然后在看内存情况,我们发现只有很少的User对象,说明User发生了逃逸,因为他们存储在栈中,随着栈的销毁而消失

在这里插入图片描述

P84 84-代码优化之同步省略

同步省略:如果一个对象被发现只有一个线程被访问到,那么对于这个对象的操作可以不考虑同步。

在这里插入图片描述
在这里插入图片描述

P85 85-代码优化之标量替换

分离对象或标量替换:有的对象可能不需要作为一个连续的内存结构存在也可以被访问到,那么对象的部分(或全部)可以不存储在内存,而是存储在CPU寄存器中。

标量替换: 就是把对象打散了分配到栈上
在这里插入图片描述

public static void main(String args[]) {
    alloc();
}
class Point {
    private int x;
    private int y;
} 
private static void alloc() {
    Point point = new Point(1,2);
    System.out.println("point.x" + point.x + ";point.y" + point.y);
}

以上代码,经过标量替换后,就会变成

private static void alloc() {
    int x = 1;
    int y = 2;
    System.out.println("point.x = " + x + "; point.y=" + y);
}

可以看到,Point这个聚合量经过逃逸分析后,发现他并没有逃逸,就被替换成两个聚合量了。那么标量替换有什么好处呢?就是可以大大减少堆内存的占用。因为一旦不需要创建对象了,那么就不再需要分配堆内存了。
标量替换为栈上分配提供了很好的基础。

在这里插入图片描述

P86 86-代码优化及堆的小结

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

第九章、方法区

尚硅谷JVM从入门到精通宋红康版|第九章、方法区

方法区主要存放的是 类(Class)信息,而堆中主要存放的是 实例化的对象

P87 87-方法区概述_栈堆方法区间的交互关系

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

栈、堆、方法区的交互关系

Person:存放在元空间,也可以说方法区
person:存放在Java栈的局部变量表中
new Person():存放在Java堆中
在这里插入图片描述

P88 88-方法区的基本理解

在这里插入图片描述
方法区主要存放的是 类(Class)信息,而堆中主要存放的是 实例化的对象
在这里插入图片描述
在这里插入图片描述

P89 89-Hotspot中方法区的演进

在这里插入图片描述
在这里插入图片描述

P90 90-设置方法区大小的参数

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

P91 91-OOM:PermGen和OOM:Metaspace举例

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

P92 92-方法区的内部结构1

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

P93 93-方法区的内部结构2

在这里插入图片描述

/**
 * non-final的类变量
 *
 * @author: 陌溪
 * @create: 2020-07-08-16:54
 */
public class MethodAreaTest {
    public static void main(String[] args) {
        Order order = new Order();
        //Order order = null;
        order.hello();
        System.out.println(order.count);
    }
}
class Order {
    public static int count = 1;
    public static final int number = 2;
    public static void hello() {
        System.out.println("hello!");
    }
}

如上代码所示,即使我们把order设置为null,也不会出现空指针异常

P94 94-class文件中常量池的理解

在这里插入图片描述

P95 95-运行时常量池的理解
P96 96-图示举例方法区的使用

P97 97-方法区在jdk6、jdk7、jdk8中的演进细节

方法区的演进细节
首先明确:只有Hotspot才有永久代。BEA JRockit、IBMJ9等来说,是不存在永久代的概念的。原则上如何实现方法区属于虚拟机实现细节,不受《Java虚拟机规范》管束,并不要求统一

Hotspot中方法区的变化:
在这里插入图片描述
JDK7的时候
在这里插入图片描述
JDK8的时候,元空间大小只受物理内存影响
在这里插入图片描述
在这里插入图片描述

P98 98-StringTable为什么要调整位置
P99 99-如何证明静态变量存在哪
P100 100-方法区的垃圾回收行为
P101 101-运行时数据区的总结与常见大厂面试题说明
P102 102-对象实例化的几种方式
P103 103-字节码角度看对象的创建过程
P104 104-对象创建的六个步骤
P105 105-对象的内存布局
P106 106-对象访问定位
P107 107-直接内存的简单体验
P108 108-使用本地内存读写数据的测试
P109 109-直接内存的00M与内存大小的设置

执行引擎

P110 110-执行引擎的作用及工作过程概述
P111 111-Java程序的编译和解释运行的理解
P112 112-机器码_指令_汇编_高级语言理解与执行过程
P113 113-解释器的使用
P114 114-HotspotVM为何解释器与JIT编译器并存
P115 115-热点代码探测确定何时JIT
P116 116-Hotspot设置模式_C1与C2编译器
P117 117-Graal编译器与AOT编译器

StringTable

P118 118-String的不可变性
P119 119-String底层Hashtable结构的说明
P120 120-String内存结构的分配位置
P121 121-两个案例熟悉String的基本操作
P122 122-字符串拼接操作的面试题讲解
P123 123-字符串变量拼接操作的底层原理
P124 124-拼接操作与append操作的效率对比
P125 125-intern()的理解
P126 126-new String()到底创建了几个对象
P127 127-关于intern()的面试难题
P128 128-面试的拓展问题
P129 129-intern()的课后练习1
P130 130-intern()的课后练习2
P131 131-intern()的空间效率测试
P132 132-StringTable的垃圾回收测试

P133 133-G1垃圾收集器的String去重操作

第十四章、垃圾回收概述

尚硅谷JVM从入门到精通宋红康版|第十四章、垃圾回收概述

P134 134-垃圾回收相关章节的说明

垃圾回收大厂面试题
蚂蚁金服
你知道哪几种垃圾回收器,各自的优缺点,重点讲一下cms和G1?
JVM GC算法有哪些,目前的JDK版本采用什么回收算法?
G1回收器讲下回收过程GC是什么?为什么要有GC?
GC的两种判定方法?CMS收集器与G1收集器的特点
百度
说一下GC算法,分代回收说下
垃圾收集策略和算法
天猫
JVM GC原理,JVM怎么回收内存
CMS特点,垃圾回收算法有哪些?各自的优缺点,他们共同的缺点是什么?
滴滴
Java的垃圾回收器都有哪些,说下g1的应用场景,平时你是如何搭配使用垃圾回收器的

京东
你知道哪几种垃圾收集器,各自的优缺点,重点讲下cms和G1,
包括原理,流程,优缺点。垃圾回收算法的实现原理
阿里
讲一讲垃圾回收算法。
什么情况下触发垃圾回收?
如何选择合适的垃圾收集算法?
JVM有哪三种垃圾回收器?
字节跳动
常见的垃圾回收器算法有哪些,各有什么优劣?
System.gc()和Runtime.gc()会做什么事情?
Java GC机制?GC Roots有哪些?
Java对象的回收方式,回收算法。
CMS和G1了解么,CMS解决什么问题,说一下回收的过程。
CMS回收停顿了几次,为什么要停顿两次?

  • 什么是垃圾?
    在这里插入图片描述

P135 135-什么是GC,为什么需要GC

在这里插入图片描述

P136 136-了解早期垃圾回收行为

在这里插入图片描述
在这里插入图片描述

P137 137-Java自动内存管理介绍

Java垃圾回收机制 ,优点:
在这里插入图片描述
Java垃圾回收机制 ,担忧:
在这里插入图片描述

GC主要关注的区域
GC主要关注于 方法区 和堆中的垃圾收集
在这里插入图片描述

第十五章、垃圾收集相关算法(面试常问)

P138 138-垃圾回收相关算法概述

垃圾回收主要包含连个阶段

  1. 垃圾标记阶段:判断对象存活一般有两种方式:引用计数算法(没有被Java使用)和可达性分析算法。
  2. 垃圾清除阶段
    在这里插入图片描述

1. 垃圾标记阶段

垃圾标记阶段:判断对象存活一般有两种方式:

  1. 引用计数算法(没有被Java使用)
  2. 可达性分析算法。

P139 139-引用计数算法的原理及优缺点(没有被Java使用)

在这里插入图片描述
标记阶段:引用计数算法

在这里插入图片描述
循环引用
当p的指针断开的时候,内部的引用形成一个循环,这就是循环引用,从而造成内存泄漏
在这里插入图片描述
在这里插入图片描述

##P140 140-Java代码举例_Python的引用计数实施方案

P141 141-可达性分析算法与GC Roots

概念
可达性分析算法:也可以称为 根搜索算法、追踪性垃圾收集

标记阶段:可达性分析算法(java使用)

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

P142 142-对象的finalization机制

在这里插入图片描述
在这里插入图片描述

由于finalize()方法的存在,虚拟机中的对象一般处于三种可能的状态(面试题)。

在这里插入图片描述
在这里插入图片描述
上图就是我们看到的Finalizer线程

P143 143-代码演示可复活的对象

代码演示
我们使用重写 finalize()方法,然后在方法的内部,重写将其存放到GC Roots中

/**
 * 测试Object类中finalize()方法
 * 对象复活场景
 *
 * @author: 陌溪
 * @create: 2020-07-12-11:06
 */
public class CanReliveObj {
    // 类变量,属于GC Roots的一部分
    public static CanReliveObj canReliveObj;

    @Override
    protected void finalize() throws Throwable {
        super.finalize();
        System.out.println("调用当前类重写的finalize()方法");
        canReliveObj = this;
    }

    public static void main(String[] args) throws InterruptedException {
        canReliveObj = new CanReliveObj();
        canReliveObj = null;
        System.gc();
        System.out.println("-----------------第一次gc操作------------");
        // 因为Finalizer线程的优先级比较低,暂停2秒,以等待它
        Thread.sleep(2000);
        if (canReliveObj == null) {
            System.out.println("obj is dead");
        } else {
            System.out.println("obj is still alive");
        }

        System.out.println("-----------------第二次gc操作------------");
        canReliveObj = null;
        System.gc();
        // 下面代码和上面代码是一样的,但是 canReliveObj却自救失败了
        Thread.sleep(2000);
        if (canReliveObj == null) {
            System.out.println("obj is dead");
        } else {
            System.out.println("obj is still alive");
        }

    }
}

最后运行结果



-----------------第一次gc操作------------
调用当前类重写的finalize()方法
obj is still alive
-----------------第二次gc操作------------
obj is dead

在进行第一次清除的时候,我们会执行finalize方法,然后 对象 进行了一次自救操作,但是因为finalize()方法只会被调用一次,因此第二次该对象将会被垃圾清除。

P144 144-使用MAT查看GC Roots

MAT是什么?
MAT是Memory Analyzer的简称,它是一款功能强大的Java堆内存分析器。用于查找内存泄漏以及查看内存消耗情况。

MAT是基于Eclipse开发的,是一款免费的性能分析工具。

大家可以在http://www.eclipse.org/mat/下载并使用MAT

使用命令行 jmap 生成Dump文件
在这里插入图片描述

P145 145-使用JProfiler进行GC Roots溯源(主要是为了查找导致内存泄漏的对象)

JProfiler的GC Roots溯源
我们在实际的开发中,一般不会查找全部的GC Roots,可能只是查找某个对象的整个链路,或者称为GC Roots溯源,这个时候,我们就可以使用JProfiler

可以直接安装运行也可以在IDEA安装Jprofiler插件
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述

P146 146-使用JProfiler分析OOM

当我们程序出现OOM的时候,我们就需要进行排查,我们首先使用下面的例子进行说明
在这里插入图片描述

/**
 * 内存溢出排查
 * -Xms8m -Xmx8m -XX:HeapDumpOnOutOfMemoryError
 * @author: 陌溪
 * @create: 2020-07-12-14:56
 */
public class HeapOOM {
    // 创建1M的文件
    byte [] buffer = new byte[1 * 1024 * 1024];

    public static void main(String[] args) {
        ArrayList<HeapOOM> list = new ArrayList<>();
        int count = 0;
        try {
            while (true) {
                list.add(new HeapOOM());
                count++;
            }
        } catch (Exception e) {
            e.getStackTrace();
            System.out.println("count:" + count);
        }
    }
}

上述代码就是不断的创建一个1M小字节数组,然后让内存溢出,我们需要限制一下内存大小,同时使用HeapDumpOnOutOfMemoryError将出错时候的dump文件输出

-Xms8m -Xmx8m -XX:HeapDumpOnOutOfMemoryError

我们将生成的dump文件打开,然后点击Biggest Objects就能够看到超大对象
在这里插入图片描述

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

然后我们通过线程,还能够定位到哪里出现OOM

2. 清除阶段

在这里插入图片描述

P147 147-标记-清除算法原理及优缺点

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

P148 148-复制算法原理及优缺点

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

P149 149-标记-压缩算法原理及优缺点

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

P150 150-不同指标上对比三种算法

在这里插入图片描述

P151 151-分代收集算法的说明

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

P152 152-增量收集算法原理及优缺点

在这里插入图片描述
在这里插入图片描述

P153 153-分区算法的说明

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

第十六章、垃圾回收相关概念

P154 154-垃圾回收相关概念的概述

P155 155-System.gc()的理解

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
代码演示是否出发GC操作

/**
 * System.gc()
 *
 * @author: 陌溪
 * @create: 2020-07-12-19:07
 */
public class SystemGCTest {
    public static void main(String[] args) {
        new SystemGCTest();
        // 提醒JVM进行垃圾回收
        System.gc();
        //System.runFinalization();
    }

    @Override
    protected void finalize() throws Throwable {
        super.finalize();
        System.out.println("SystemGCTest 执行了 finalize方法");
    }
}

在这里插入图片描述
即如果调用 System.gc();不一定会触发finalize方法,打印SystemGCTest 执行了 finalize方法,而如果调用System.runFinalization()会强制调用,并打印

运行结果,但是不一定会触发销毁的方法,调用System.runFinalization()会强制调用 失去引用对象的finalize()

/**
 * System.gc()
 *
 * @author: 陌溪
 * @create: 2020-07-12-19:07
 */
public class SystemGCTest {
    public static void main(String[] args) {
        new SystemGCTest();
        // 提醒JVM进行垃圾回收
        System.gc();
        //System.runFinalization();
    }

    @Override
    protected void finalize() throws Throwable {
        super.finalize();
        System.out.println("SystemGCTest 执行了 finalize方法");
    }
}

P156 156-手动gc理解不可达对象的回收行为

P157 157-内存溢出的分析

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

P158 158-内存泄漏的分析

在这里插入图片描述

java使用的是可达性分析算法,内存泄漏都是针对可达性分析算法说的
在这里插入图片描述
内存泄漏举例:
在这里插入图片描述

P159 159-StopTheWorld事件的理解

在这里插入图片描述
在这里插入图片描述

P160 160-程序的并行与并发

在这里插入图片描述
并行要求cpu是多核
在这里插入图片描述
在这里插入图片描述

P161 161-垃圾回收的并行与并发

在这里插入图片描述
在这里插入图片描述

P162 162-安全点与安全区域的说明

在这里插入图片描述
面试会问:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

P163 163-Java中几种不同引用的概述(面试题)

在这里插入图片描述
在这里插入图片描述

P164 164-强引用:不回收

在这里插入图片描述
举例
强引用的案例说明

StringBuffer str = new StringBuffer("hello mogublog");

局部变量str指向stringBuffer实例所在堆空间,通过str可以操作该实例,那么str就是stringBuffer实例的强引用对应内存结构:
在这里插入图片描述

如果此时,在运行一个赋值语句

StringBuffer str = new StringBuffer("hello mogublog");
StringBuffer str1 = str;

对应的内存结构为:
在这里插入图片描述

那么我们将 str = null; 则 原来堆中的对象也不会被回收,因为还有其它对象指向该区域
在这里插入图片描述

P165 165-软引用:内存不足即回收

在这里插入图片描述
注意,这里的第一次回收是不可达的对象
在这里插入图片描述

// 声明强引用
Object obj = new Object();
// 创建一个软引用
SoftReference<Object> sf = new SoftReference<>(obj);
obj = null; //销毁强引用,这是必须的,不然会存在强引用和软引用

在这里插入图片描述

P166 166-弱引用:发现即回收

在这里插入图片描述

P167 167-虚引用:对象回收跟踪

在这里插入图片描述
在这里插入图片描述

// 声明强引用
Object obj = new Object();
// 声明引用队列
ReferenceQueue phantomQueue = new ReferenceQueue();
// 声明虚引用(还需要传入引用队列)
PhantomReference<Object> sf = new PhantomReference<>(obj, phantomQueue);
obj = null; 

案例
我们使用一个案例,来结合虚引用,引用队列,finalize进行讲解

/**
 * @author: 陌溪
 * @create: 2020-07-12-21:42
 */
public class PhantomReferenceTest {
    // 当前类对象的声明
    public static PhantomReferenceTest obj;
    // 引用队列
    static ReferenceQueue<PhantomReferenceTest> phantomQueue = null;

    @Override
    protected void finalize() throws Throwable {
        super.finalize();
        System.out.println("调用当前类的finalize方法");
        obj = this;
    }

    public static void main(String[] args) {
        Thread thread = new Thread(() -> {
            while(true) {
                if (phantomQueue != null) {
                    PhantomReference<PhantomReferenceTest> objt = null;
                    try {
                        objt = (PhantomReference<PhantomReferenceTest>) phantomQueue.remove();
                    } catch (Exception e) {
                        e.getStackTrace();
                    }
                    if (objt != null) {
                        System.out.println("追踪垃圾回收过程:PhantomReferenceTest实例被GC了");
                    }
                }
            }
        }, "t1");
        thread.setDaemon(true);
        thread.start();

        phantomQueue = new ReferenceQueue<>();
        obj = new PhantomReferenceTest();
        // 构造了PhantomReferenceTest对象的虚引用,并指定了引用队列
        PhantomReference<PhantomReferenceTest> phantomReference = new PhantomReference<>(obj, phantomQueue);
        try {
            System.out.println(phantomReference.get());
            // 去除强引用
            obj = null;
            // 第一次进行GC,由于对象可复活,GC无法回收该对象
            System.out.println("第一次GC操作");
            System.gc();
            Thread.sleep(1000);
            if (obj == null) {
                System.out.println("obj 是 null");
            } else {
                System.out.println("obj 不是 null");
            }
            System.out.println("第二次GC操作");
            obj = null;
            System.gc();
            Thread.sleep(1000);
            if (obj == null) {
                System.out.println("obj 是 null");
            } else {
                System.out.println("obj 不是 null");
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {

        }
    }
}

最后运行结果

null
第一次GC操作
调用当前类的finalize方法
obj 不是 null
第二次GC操作
追踪垃圾回收过程:PhantomReferenceTest实例被GC了
obj 是 null

P168 168-终结器引用的介绍(了解即可)

第十七章、垃圾回收器

P169 169-垃圾回收器章节概览

在这里插入图片描述
Java不同版本新特性

语法层面:Lambda表达式、switch、自动拆箱装箱、enum
API层面:Stream API、新的日期时间、Optional、String、集合框架
底层优化:JVM优化、GC的变化、元空间、静态域、字符串常量池位置变化

P170 170-垃圾回收器的分类

  1. 按线程数分
    按线程数分(垃圾回收线程数),可以分为串行垃圾回收器和并行垃圾回收器。
    在这里插入图片描述
    在这里插入图片描述
  2. 按工作模式分
    按照工作模式分,可以分为并发式垃圾回收器和独占式垃圾回收器。

在这里插入图片描述
在这里插入图片描述

P171 171-GC性能指标的整体说明

在这里插入图片描述
在这里插入图片描述

P172 172-吞吐量与暂停时间的对比说明

现在标准:在最大吞吐量优先的情况下,降低停顿时间

性能指标:吞吐量
在这里插入图片描述
性能指标:暂停时间
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

P173 173-垃圾回收器的发展迭代史

在这里插入图片描述
GC垃圾收集器是和JVM一脉相承的,它是和JVM进行搭配使用,在不同的使用场景对应的收集器也是有区别
在这里插入图片描述

在这里插入图片描述
serial parNew parallel scavenge

7种经典的垃圾收集器
在这里插入图片描述
在这里插入图片描述

P174 174-垃圾回收器的组合关系

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

P175 175-如何查看默认的垃圾回收器

-XX:+PrintcommandLineFlags:查看命令行相关参数(包含使用的垃圾收集器)

使用命令行指令:jinfo -flag 相关垃圾回收器参数 进程ID

在这里插入图片描述

在这里插入图片描述

P176 176-Serial与Serial Old垃圾回收器的介绍(基本不用,了解即可)

Serial与Serial Old垃圾回收器主要用于单核CPU的场景
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

P177 177-如何设置使用Serial垃圾回收器

在HotSpot虚拟机中,使用-XX:+UseSerialGC参数可以指定年轻代和老年代都使用串行收集器。

等价于新生代用Serial GC,且老年代用Serial old GC
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

P178 178-ParNew垃圾回收器的介绍

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

P179 179-如何设置使用ParNew垃圾回收器

P180 180-Parallel与Parallel Old垃圾回收器的介绍

Parallel与Parallel Old垃圾回收器 :吞吐量优先
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

P181 181-Parallel垃圾回收器的相关参数设置

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

P182 182-CMS垃圾回收器概述与工作原理

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

P183 183-CMS的特点与弊端分析

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

P184 184-CMS垃圾回收器的参数设置

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

P185 185-CMS的小结及后续JDK版本中的变化

在这里插入图片描述
在这里插入图片描述

P186 186-认识G1垃圾回收器

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

P187 187-G1垃圾回收器的优势和不足

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

P188 188-G1的参数设置

在这里插入图片描述

在这里插入图片描述

P189 189-G1在生产环境的适用场景

在这里插入图片描述

P190 190-region的使用介绍

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

P191 191-G1垃圾回收器的主要回收环节

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

P192 192-记忆集与写屏障

在这里插入图片描述

在这里插入图片描述

P193 193-G1垃圾回收过程的详细说明

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

P194 194-G1垃圾回收的优化建议

在这里插入图片描述
在这里插入图片描述

P195 195-7种经典的垃圾回收器总结与调优建议

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

P196 196-常用的显示GC日志的参数

在这里插入图片描述

在这里插入图片描述

JDK8默认垃圾回收器: 年轻代用parallel scavege,老年代用parallel old

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

方法区在jdk1.7的落地实现叫永久代,在jdk1.8的落地实现叫元空间

JDK9默认垃圾回收器:G1
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

P197 197-GC日志中垃圾回收数据的分析

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

GC:
在这里插入图片描述
Full GC
在这里插入图片描述

P198 198-举例说明日志中堆空间数据如何解读

在这里插入图片描述
在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
JDK1.7 JDK1.7对于新来的新生代edno区剩余空间放不下的大对象,会将endo的对象全部放到老年代,把新来的大对象再放到endo区
在这里插入图片描述

GC后

在这里插入图片描述

jdk1.8 JDK1.8会将新来的新生代edno区剩余空间放不下的大对象直接放到老年代
在这里插入图片描述
在这里插入图片描述

P199 199-日志分析工具的使用

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

建议使用GCeasy
在这里插入图片描述

P200 200-新时期的Epsilon和Shenandoah垃圾回收器

在这里插入图片描述

P201 201-革命性的ZGC的性能介绍

在这里插入图片描述

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

P202 202-其他的厂商的垃圾回收器
在这里插入图片描述

已标记关键词 清除标记
相关推荐
©️2020 CSDN 皮肤主题: 数字50 设计师:CSDN官方博客 返回首页