JVM学习笔记

JVM简单介绍

​ JVM (Java Virtual Machine 即java虚拟机),在引入java虚拟机后,对java源文件(.java)通过java虚拟机编译成字节码文件(.class),可在其他安装java虚拟机平台直接运行,实现“一次编译,多次运行”。

Java虚拟机不仅是一种跨平台的软件,而且是一种新的网络计算平台。该平台包括许多相关的技术,如符合开放接口标准的各种API、优化技术等。Java技术使同一种应用可以运行在不同的平台上。Java平台可分为两部分,即Java虚拟机(Java virtual machine,JVM)和Java API类库。

​ 编译性语言,也就是讲源文件编译成二进制字符文件,通过虚拟机可直接运行;编译性语言执行速度快,但跨平台能力相较于解释性语言差。

​ 解释性语言,直接将源文件执行,通过解释器;执行速度较慢,但其夸平台能力强。

​ JVM的主要作用:类加载器classloader加载class文件;编译源文件并执行;内存分配及垃圾回收。

JVM内存模型图

JVM加载机制

类的加载过程

​ 类加载到卸载分为七个阶段:加载->验证->准备->解析->初始化->使用->卸载

  • 加载:在使用到该类时,通过该类全名读取到该字符吗文件,并在加载阶段在内存生成一个java.lang.class对象,作为访问的入口。

  • 验证:就是验证该加载类是否符合规定的规范条件,大致为:文件格式验证、元数据验证、字节码验证、符号引用验证。

  • 准备:也就是给类的静态变量赋值(默认值,不同的数据类型默认值不同)并分配内存;静态常量(static final修饰)会在准备阶段直接赋值,而静态值(static修饰)在准备阶段是为默认值,但在类初始化时进行赋值。

  • 解析:将字节码文件中的符号引用转化为直接引用。

  • 初始化:初始化就是执行类构造器的过程,虚拟机在子类初始化时,会调用父类,以确保子类的正常初始化。

  • 使用:也就是执行类中的具体内容。

  • 卸载:一个类何时结束生命周期,取决于其所代表的Class类(方法区中的类)结束生命周期。在虚拟机中自带的类加载器中的类,在虚拟机的声明周期内不会被卸载。

    类可被回收的条件:该类的所有的实例对象都已被回收,堆中不存在任何类的实例对象;加载该类的ClassLoader已被回收;该类的java.lang.Class对象没有在任何地方被引用到,无法在任何地方通过反射访问到该类的方法。

JVM类加载

类加载器详解

类加载器简介

​ 类加载器顾名思义就是,实现加载类的作用(即通过类全名加载到二进制字节流文件)。对于任何类,都需要它的加载器和该类在java虚拟机中确保其唯一性(两个类是否相同,其条件就是来自同一个class文件并且为同一类加载器加载)。

​ 类加载机制的类型:

  • 全责加载,顾名思义就是加载一个类时,该类的依赖及对于其他类的引用,都由同一个类加载器加载;

  • 双亲委派,也就是让其父类加载器加载,倘若父类加载器失效,则由子类加载器加载;

  • 缓存机制,也就是在加载过的加载类,会将其存储到缓存中, 当某个类需要该类时直接从缓存区中加载,若缓存区中无该类,则通过类加载器加载,后缓存进入缓存区中;

双亲委派模型

  • 启动类加载器(Bootstarp ClassLoader):该类加载器由C/C++语言所写,该启动加载器没有父加载器,且启动加载器为拓展加载类与应用加载器的父加载器。

  • 扩展类加载器(Extension ClassLoader):由java语言所写,其父类启动器为启动类加载器,且为应用类加载器的父加载器。负责加载JDK中一些特殊的模块。

  • 应用类加载器(APP ClassLoader):父类加载器为拓展加载器,其负责加载环境变量classpath或系统属性java.class.path指定路径下的类库。

双亲委派

JVM内存结构

JVM内存结构

​ JVM内存结构大致分为五个结构:程序计数器、虚拟栈(Stark)、本地方法栈、堆(Heap)、方法区;

  • **程序计数器:**用于存储下一条指令所在单元的地址的地方;字节码解释器工作时通过改变这个计数值可以选取下一条需要执行的字节码指令,分支、循环、跳转、异常处理和线程恢复等功能都需要依赖这个计数器完成;没有垃圾回收;它包含当前正在执行的指令的地址(位置)。当每个指令被获取,程序计数器的存储地址加一。在每个指令被获取之后,程序计数器指向顺序中的下一个指令。当计算机重启或复位时,程序计数器通常恢复到零
  • 虚拟栈:也就是常叫的栈内存空间,该栈内存相较于堆空间较小,且属于线程私有其生命周期与线程相同,并且是先进后出原则。每个方法执行时,都会创建一个栈帧,用于存储局部变量表、操作数栈、动态链接和方法出口等信息。
  • **本地方法栈:**其内部结构与虚拟栈结构相同,其服务用于Native 方法服务。
  • 堆:所有线程共享的区域,所有的实例对象在此处创建,并且在此处经常发生垃圾回收操作,简单理解就是所有通过new创建实例对象,都存储在堆内存中。
  • 方法区:方法区主要存储一些静态信息,如虚拟机已加载的类信息、 常量值、静态变量和编译后的代码数据等;方法区中含有一个静态常量池,用于存储静态编译产生的字面量和符号引用; 该空间是线程共享的,且该区域很少发生GC垃圾回收,但并不代表不会发生GC垃圾回收,发生GC主要对常量池和方法类型进行回收;

类创建过程

栈内存详解

  • 栈是与每一个线程关联的,当一个线程创建会在栈中创建一个栈帧,故栈帧的生命周期与线程的生命周期相同。

  • 线程是否安全?线程安全线程私有,栈内存储方法内部的局部变量;

  • 当栈内存不够时,也就会抛出 StackOverflowError

  • 设置栈帧内存大小(调用的次数,若栈帧存储的数据变大,则其调用的次数会变少);

堆内存详解

堆内存空间

  • 堆内存的划分成三个部分:新生代(Eden 伊甸园、Survivor 幸存区)、老年代元空间

  • 堆内存中GC流程:通过new的对象也就是新创建的对象,会在新生代中的 Eden 伊甸园 中创,若Eden中的空间不足则会发生GC垃圾回收,若进行GC后其伊甸园内存任不足,回收垃圾对象并将未被回收的会移动到幸存区(FROM-TO),以拓展伊甸园内存空间,如此当幸存区中的内存不足,则会进行GC,并将其幸存的对象移动到老年代。

  • 设置Heap堆区的内存大小:

    • -Xms:设置初始分配大小,默认为物理内存的1/64

    • -Xmx:最大分配内存,默认为物理内存的1/4

    • -XX:+PrintGCDetails:输出详细的GC处理日志

    • -XX:+PrintGCTimeStamps:输出GC的时间戳信息

    • -XX:+PrintGCDateStamps:输出GC的时间戳信息(以日期的形式)

    • -XX:+PrintHeapAtGC:在GC进行处理的前后打印堆内存信息

    • -Xloggc:(SavePath):设置日志信息保存文件

对象引用详解

​ 对象引用分为:强引用、软引用、弱引用、虚引用

  • 强引用:即通过new的对象,也就是还在被使用就是还有强引用指向对象,或被引用的在发生GC后不会被回收。
  • 软引用:该生命周期相较于强引用其生命走起小,在内存不足时进行GC垃圾回收会清理该对象。
  • 弱引用:在发生GC垃圾回收时就会回收该对象。
  • 虚引用:虚引用必须与引用队列联合使用,当发生GC时回收对象,但发现该对象为虚引用,则会将该虚引用加入相关的引用队列中。

JVM垃圾回收

GC垃圾判断策略

  • 垃圾对象,就是未被使用的对象或者未被指针指向的对象,会被划分为垃圾对象范围内。

  • 垃圾对象的规划方式:引用计数、可达性分析等。

    • 引用计数(python采用):每个对象添加一个计数器,被使用到的添加递增次数,未被使用的其使用次数为0,则将其划分为垃圾对象;该有一个致命的缺点,就是循环引用 这会导致其他对象都不能被回收。

    • 可达性分析(java、C#等采用):类似于树深度优先搜索,从GC ROOT根节点出发,向下遍历,与根节点没有任何关系对象的,全部标记为垃圾对象。

可达性分析

GC垃圾回收算法

  • 标记清除算法(Mark-Compact):通过可达性分析标记垃圾对象与存留对象,然后对垃圾对象进行回收,此处含有内存碎片残留,该算法效率低。

标记清除算法

  • 复制算法(Cpoying):复制移动算法对与内存的使用只有一半,先进行可达性分析标记垃圾对象,删除垃圾对象后将已使用的对象移动到另一半的内存空间中,该算法内存效率高,不容易产生内存碎片;但是当对象过多时,算法的效率会大大降低。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-pEub3lWy-1652070044596)(https://cdn.jsdelivr.net/gh/SILENTI/Imgs/JVM-GC%E7%AE%97%E6%B3%95%20%E5%A4%8D%E5%88%B6%E7%A7%BB%E5%8A%A8.png)]

  • 压缩整理算法(Mark-Compact):该算法是对标记算法与复制移动算法的整合,完全使用内存,无碎片残留, 无内存浪费;该算法会先进行可达性分析标记出可回收对象与存活对象,后将存活对象移动到另一端,后对回收对象进行回收。

压缩整理算法

  • 标记整理 > 复制删除 > 压缩整理

GC垃圾回收器

​ GC垃圾回收器:串行垃圾回收器(Serial GC)、并行垃圾回收器(Parallel GC)、并发垃圾回收器(CMS GC)、G1垃圾回收器;

垃圾回收器

  • 串行垃圾回收器 (Serial)

​ 串行垃圾回收器(Serial)为第一个垃圾回收器,单线程模式,故不支持线程并发进行,当发生GC垃圾回收时,会暂停所有的用户线程,适用于小内存单核CPU的场景。

​ 该新生代采用复制算法,老年代采用压缩整理算法。

Serial 垃圾处理器

  • 并行垃圾回收器

    • ParNew 垃圾回收器

      ParNew垃圾回收器也就是Serial垃圾回收器的多线程版本,除在新生代采用多行程,其余与Serial垃圾回收器相同。

    ParNew 垃圾处理器

    • Parallel 垃圾回收器

​ 吞吐量优先,新生代采用复制算法,老年代采用标记整理算法,并两过程多线程处理。

Parallel 垃圾回收器

  • 并发垃圾回收器(CMS)

​ CMS是用于老年代的垃圾回收器,采用标记-清除算法,且与用户线程并发进行。

CMS 垃圾回收器

  • G1 垃圾回收器(G1)

​ G1垃圾回收器是适用于新生代和老年代共用的垃圾回收器,适用于超大内存中使用,整体上是标记+整理算法,两个区域之间是复制算法。
老年代采用标记整理算法,并两过程多线程处理。

[外链图片转存中…(img-pgkOnjUV-1652070044614)]

  • 并发垃圾回收器(CMS)

​ CMS是用于老年代的垃圾回收器,采用标记-清除算法,且与用户线程并发进行。

[外链图片转存中…(img-FuyTm2qp-1652070044618)]

  • G1 垃圾回收器(G1)

​ G1垃圾回收器是适用于新生代和老年代共用的垃圾回收器,适用于超大内存中使用,整体上是标记+整理算法,两个区域之间是复制算法。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值