天天看点

详解JVM和GC垃圾回收

文章目录

    • JVM架构图分析
      • Java虚拟机运行时数据区
      • 对象的创建方式有几种?
      • 创建对象的过程
      • 对象的访问定位
    • 垃圾回收机制
      • 如何判断一个对象是否可以回收
      • 垃圾回收算法都有哪些?
      • 对象分代
    • 垃圾回收器
      • CMS垃圾回收器
      • G1垃圾收集器
    • 类加载机制
      • 类装载执行过程
      • 类加载器有哪些?
      • 双亲委派模型

JVM架构图分析

详解JVM和GC垃圾回收

我们编写的代码是java源文件.java文件,经过编译器编译成字节码文件.class文件,通过类装载器装载进jvm内存区域。

Java虚拟机运行时数据区

程序计数器:当前线程的行号指示器,用来记录当前执行到代码的哪一行、

Java虚拟机栈:存局部变量表,操作数栈,动态链接,方法出口等

本地方法栈:与虚拟机栈一样,只不过调用native服务

Java堆:存放数组,和对象实例,该区域线程共享

方法区:也叫永久代,存类信息,常量,静态变量。在jdk1.8取消了方法区,叫原空间,直接有直接内存管理

对象的创建方式有几种?

1 new关键字 通过构造方法创建

2 Class的newInstance 构造方法

3 Constructor类的呢哇Instance 构造方法

4 clone

5 反序列化

创建对象的过程

new 判断类是否加载

分配内存 指针碰撞,空闲列表

并发处理 CAS同步

初始化

init

对象的访问定位

直接指针:直接指向对象地址

句柄访问:指向指针的指针

在java堆中会维护一个句柄池,来装句柄,当对象发生改变的时候,只需要改变句柄池中的句柄就可以

垃圾回收机制

如何判断一个对象是否可以回收

1 引用计数器法:每个对象被引用一次,该对象的计数器加一,引用完计数器减一,到0 的时候可以被垃圾回收。

问题:对象之间相互引用,永远无法被垃圾回收

2可达性分析法:通过GCRoot形成一个引用链,只要是引用链可达的对象,就不会垃圾回收

垃圾回收算法都有哪些?

1 标记清除: 先标记垃圾,然后对垃圾对象进行垃圾回收。

问题:产生内存碎片

2 标记整理: 先标记垃圾,在对垃圾进行整理,不会产生内存碎片,但是降低了回收效率

3 复制算法:当一般空间满了的时候,就会把非垃圾回收对象复制到另一半内存,然后把那一半内存垃圾回收

问题:浪费一半的内存

4分代垃圾回收

对象分代

按存周期来分成 年轻代,老年代 , 永久代

年轻代占3分一1 老年代占3分之2

年轻代分为三个区域,Eden,Survivor from ,Survivor to 默认比例是8:1:1

对象会被先分 分配到Eden区,经过一次MinorGC进入from区,from和to区交换指针,对象年龄加1 ,对象到达15岁会进入老年代。

大对象Eden放不下,会直接进入老年代

垃圾回收器

一共有7种垃圾回收器

Serial(复制算法):是年轻代单线程的垃圾回收器

ParNew(复制算法):是年轻代多线程的垃圾回收器

Parallel Scavenge(复制算法):多线程 高吞吐,高cpu

SerialOld(标记整理):单线程,Serial老年代版本

ParallelOld(标记整理):多线程,老年代

CMS(标记清除):老年代并行收集器,追求最短停顿

G1收集器(标记整理):整个堆垃圾回收器

CMS垃圾回收器

1 初始标记—》stop the world

2 并发标记 --》

3 重新标记 --》stop the world

4并发清除

G1垃圾收集器

G1将整个堆分称大小固定的独立区域(Region),跟踪这些区域的垃圾堆积程度,维护一个优先级队列,优先回收垃圾最多的区域

类加载机制

类装载方式:

1 隐式装载: new

2 显示装载: class.forName

类装载执行过程

1 加载: 找到对应的class文件

2 验证:检查加载的class文件的正确性

3准备:给类中静态变量分配内存

4 解析:将常量池中的符号引用转化成直接引用

5 初始化:静态变量,静态代码块初始化

类加载器有哪些?

1 启动类加载器

2 扩展类加载器

3 系统类加载器

4 用户自定义加载器

双亲委派模型

接到加载请求的时候,自己先不去处理,交给自己的父类去处理,最顶层父类处理不了,再逐级向下加载。

1、防止重复加载同一个.class。通过委托去向上面问一问,加载过了,就不用再加载一遍。保证数据安全。

2、保证核心.class不能被篡改。通过委托方式,不会去篡改核心.clas,即使篡改也不会去加载,即使加载也不会是同一个.class对象了。不同的加载器加载同一个.class也不是同一个Class对象。这样保证了Class执行安全。