全网最好的JVM总结:有生命周期的JVM

news2025/5/24 13:27:29

1.编译

1.1 java中编译器有哪些?

  • 前端编译器 javac
  • 后台即时编译器 JIT编译器
  • 静态提前编译器 (一步到位,直接把java编译成二进制)

2.2 编译过程是怎么样?

  1. 解析与填充符号表,生成语法树 (编译原理的东西)
  2. 插入式注解处理器的处理过程,对语法树进行操作 (jvm提供了一些钩子方法对语法树进行修改)比较有名的lombok、阿里的checkStyle
  3. 字节码生成

2.3 解释器和编译器怎么搭配使用的?

  1. 当虚拟机启动之后,解释器根据预定义的规范对字节码逐行解释,解释生成对应平台的机器码
  2. 后台编译器在运行过程中,对代码进行不断的优化,常见的优化有:方法内联、去虚拟化、栈上分配
  3. 为什么要2个搭配使用?随着程序启动,解释器可以首先发挥作用,而不是等后台编译器全部编译完再执行,即时编译器后期再慢慢优化

2.字节码

2.1 字节码长什么样?

  1. 咖啡baby
  2. 大版本+小版本
  3. 常量池:常亮池中的内容大致可以这么理解:
    1. 用utf-8 info这个类型来表示字节码,比如 private Integer i 用2个utf-8 info类型 Integer、i,
    2. 然后各种属性类型、方法类型来引用这个utf-8Info, 比如 field_info 指向前面2个utf-8 info类型
  4. 属性表集合
  5. 方法表集合

image.png

2.2 字节码怎么玩

image.png

  • ASM派 ASM => Byte Buddy =>cglib
  • Javassist派 Javaassist

JDK、CGLIB、Javassist和ASM的动态代理使用对比_xiaoliuliu2050的博客-CSDN博客

3.类加载

3.1 类加载的来源

  1. 文件
  2. 网络
  3. 动态代理

3.2 类加载的过程

  1. 加载
  2. 链接
    1. 验证 验证这个类文件对不对
    2. 准备 给类变量赋初值
    3. 解析 将运行时常量池里面的符号引用转换为直接引用
  3. 初始化
  4. 使用
  5. 卸载

!!! 解析和初始化的顺序不是确定的,为了动态绑定,先初始化,再解析

3.3 哪些情况会进行类的初始化

  1. 使用new
  2. getStatic、putStatic、invokeStatic这几条字节码指令,就是说我想要操作类变量的时候,不管是属性还是方法,都会导致类加载
  3. 对类进行反射调用
  4. 初始化类的时候,如果父类没有初始化,需要初始化父类
  5. 虚拟机启动时,用户需要指定一个执行的主类(main),虚拟机就会初始化这个类

3.4 类加载和类初始化的理解

类加载不代表类初始化了,类初始化就代码类肯定加载了。XXX.class就只是加载了类,但是并没有类初始化。

3.5 几个类加载

  1. Bootstrap ClassLoader 加载核心类库,rt.jar
  2. Extension ClassLoader 拓展类加载 /jre/ext/xxx.jar
  3. Applicaiton ClassLoader 系统类加载 加载ClassPath上的类
  4. 自定义加载器

3.6 为什么要使用双亲委派

保证核心类库的安全

4.运行时数据区 jvm | ProcessOn免费在线作图,在线流程图,在线思维导图 |

image.png

4.1 方法区

4.1.1 方法区的理解

在类加载之后,把字节码静态数据转换为运行时的数据结构,比如常量池->运行时常量池;常量池之后的类、方法、属性啊 ->上图中的类信息、属性、方法信息等;另外在堆中创建一个Class对象作为方法区的入口



4.2.2 方法区存放哪些内容

  • 运行时常量池
  • 类信息 (类、属性、方法)

4.2.3 方法区的演进过程

image.png

  • 在1.8之前称为永久代,里面存放的 运行时常量池(包含字符串常量池)、类信息、静态变量等
  • 1.8之后换为元空间,将静态变量、字符串常量池放到堆里面
  • 为什么把永久代换成元空间,随着各种动态加载框架的使用,永久代空间设置很难确定,那么我们是不是可以放到jvm内存之外来分配哪,用元空间就解决了这个问题

4.2 堆

4.2.1 堆的组成结构

  • 新生代
    • Eden区
    • Survivor区
    • Eden:Survivor1: Survivor2 = 8:1:1
  • 老年代

4.3 虚拟机栈

1个线程就有1个虚拟机栈,线程方法调用就是栈帧的入栈和出栈

4.3.1 栈帧里面有什么

  • 局部变量表
  • 操作数栈 :局部变量表通过操作数栈来完成一些运算
  • 动态链接:多态的时候,想要知道这个方法到底属于哪个类的方法,所以栈帧会有一个指向运行时常量池的方法引用
  • 返回地址:存放调用方法的pc寄存器的值,我得知道上一个方法地址是多少

4.4 本地方法栈

在hotspot中,本地方法栈和虚拟机栈实现方式一样,本地方法栈调用的都是native方法

4.5 程序计数器

唯一不会出现OOM的内存区域

4.6 对象的创建过程

Car car = new Car(); car.start();

  1. 类加载:当遇到new指令时,虚拟机检查Car能否在运行时常量池中定位到它的符号引用,如果没有,那就进行类加载,结果:将类加载进方法区,堆生成一个Class对象,方便访问
  2. 对象内存分配:给对象分配一块内存,分配出现并发问题解决方案:1、CAS自旋 2、TLAB 本地分配(在eden中给每个线程分配了一块内存),结果:在Eden区中分配一块内存给Car对象
  3. 对象内存初始化:Jvm初始化分配好的内存,将其设为零值。结果:Car对象的实例都是有初始数据的
  4. **设置对象头: **1、设置markword(hashcode、GC分代年龄、锁标志、锁信息)2、设置类型指针(指向堆里面的class对象)

image.png
image.png

  1. **执行构造函数:**最后执行构造函数,对属性赋值。
  2. **Car引用指向 Car对象:**这里引用有哪些?强软(内存不够回收)弱(gc回收)虚 (随时可能回收)
  3. **创建栈帧入栈:**创建start栈帧入栈

5. GC

创建完对象,系统开始运行起来了,但是随着越来越多的对象创建并执行,内存是不是不够了,内存不够怎么办,那就是垃圾回收

5.1 怎么知道哪些对象要回收

  • 引用计数法 :可能存在循环引用,导致gc不了的问题
  • 可达性分析算法:在hotspot中使用的是可达性分析算法,从GC Roots往下往下开始遍历,看GC Roots上有没有对象引用到它,如果没有,就考虑要回收了

5.2 GC Roots哪些

  • 局部变量
  • 静态变量

5.3 怎么回收(算法)

  • 复制算法

将内存一分为二,在同一时间只会使用其中一块内存,GC的时候只要标记出存活对象,然后把存活对象移到另外一半内存中就行

  • 优点:简单快速、内存完整

  • 缺点:内存利用率低

  • 标记清除

    GC的时候标记出所有存活对象,然后把没有标记的对象全部清理掉

    • 优点:简单
    • 缺点:会产生大量的内存碎片
  • 标记整理

GC的时候标记出所有存活对象,然后把没有标记的对象清理掉,并将存活对象挪到到内存一端。

  • 优点:内存完整
  • 缺点:效率不是很高

5.4 怎么回收(实践)

有了算法,当然有对应的垃圾回收器,比如Serial、ParNew、ParallelScavenge、CMS、G1等等。
根据新生代和老年代的特点,最终是这样的:
image.png

  • 新生代 朝生夕灭,存活对象不多,所以使用复制算法
  • 老年代 对象存活对象比较多,所以使用整理或者清除算法

新生代:Serial 单线程、ParNew 多线程、Parallel 吞吐量
老年代:SerialOld 单线程、 Paralle Old、CMS

一般来说,内存小一点的用 parNew + cms, 内存大一点的就直接上g1了

5.5 CMS的工作原理

  1. 初始标记 简单的找一下 GC Roots
  2. 并发标记 GC线程和用户线程并发执行,从GC Roots开始标记需要清理的对象
  3. 重新标记 在并发执行的时候,肯定又会产生很多垃圾,所以需要重新标记需要清理的对象
  4. 并发清理 将需要清理的对象全部清理掉

也就说它把stop world处理的时间分散在和用户线程并发处理中了

5.6 CMS可能会出现的一些问题

  • CMS老年代垃圾回收的默认触发比例是92%,也就是说92%的时候会触发老年代回收,如果在并发清理的时候,又有对象进入老年代,假设老年代不够,就会使用Serial Old去Stop World来回收老年代所有对象,一旦使用Serial Old来回收内存,非常的耗时
  • CMS使用的标记清除,会存在内存碎片,所以CMS给了参数CMS的另外一个参数 -XX:+UseCMSCompactAtFullCollection,就是说在几个Full Gc之后需要执行一次内存碎片整理的

5.6 G1的工作原理

  • G1会把内存分为很多Region,默认是2048个,假设设置堆内存4G,那就是每个Region2M
  • 新生代初始占比5%,也就是大概100个region,接着JVM会不断增加Region,但是不会超过60%
  • 尽管G1取消了新生代、老年代,但是其实对于Region来说还是有逻辑的分代思想
  • 新生代里面还有Eden和Survivor,默认也是8:1:1。在创建Eden的同时也会创建Survivor。
  • 当新生代Region超过 60%,就触发垃圾回收,会把Eden的Region放到S1中Region中,不过在回收的时候需要考虑停顿时长200ms,如果设置了,就需要保证回收时长不能大于200ms
  • Region里面的新生代慢慢也会存放到老年代中

5.7 三色标记

  • 初始状态对象都是白色
  • CMS和G1在初始标记的时候,GC Roots 标记为灰色
  • 并发标记的时候,扫描整个引用链,有子节点的话,当前节点标记为黑色,子节点为灰色
  • 重复上面的过程,最后

image.pngA D2个是灰色
image.pngAD 2个变成黑色,E是灰色
image.pngEFG变成黑色,清理白色 BCH

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1593444.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

java学习之路-继承

文章目录 前言 目录 1.1继承的概念 1.2继承有什么好处,为何要继承 1.3继承的语句 1.4父类成员的访问 1.4.1 子类中访问父类的成员变量 1.4.2 子类中访问父类的成员方法 1.5 super关键字 2.子类构造方法 2.1如何创建构造方法 2.2创建构造方法 3.super和this 【相同点…

Centos7 K8S 集群 - kubeadm搭建方式

机器准备 搭建环境是centos7, 四核心4G内存四台机器 一个master节点,一个etcd,两台node 机器名称IP 地址master192.168.1.127node1192.168.1.129node2192.168.1.130node3192.168.1.131 机器时间同步 各节点时间要求精确同步,可以直接联网…

web自动化测试系列-selenium xpath定位方法详解(六)

1.xpath介绍 XPath 是一门在 XML 文档中查找信息的语言。XPath 用于在 XML 文档中通过元素和属性进行导航。而html中也应用了这种语言 ,所以 ,我们定位html页面元素时也会用到xpath这种方法 。 2.xpath定位方式 xpath主要通过以下四种方法定位 &#…

【第二十九篇】BurpSuite杂项综合

文章目录 Intruder模块URL编码Grep检索提取logger日志模块Intruder模块URL编码 假设我们需要对GET请求包中的URL目录进行爆破FUZZ: example.com/xxxx(文件名)Intruder模块会自动对我们的文件名字典进行URL编码 例如payload为1.txt时,burp对其进行URL编码并连接到example.c…

VMware安装Red Hat7.9

1、下载Red Hat Enterprise Linux7.9版本 【百度网盘下载】 链接:https://pan.baidu.com/s/1567NfZRF48PBXfUqxumvDA 提取码:bm7u 2、在虚拟机中创建Red Hat7.9 【点击创建虚拟机】 【自定义高级】 【选择光盘映像安装】 全名自定义即可 【虚拟机命…

Windows环境下删除MySQL

文章目录 一、关闭MySQL服务1、winR打开运行,输入services.msc回车2、服务里找到MySQL并停止 二、卸载MySQL软件1、打开控制模板--卸载程序--卸载MySQL相关的所有组件 三、删除MySQL在物理硬盘上的所有文件1、删除MySQL的安装目录(默认在C盘下的Program …

【截至2023年底】语言模型的发展

什么是大语言模型LLM?ChatGPT、LLAMA各自有什么优势? from: https://www.youtube.com/watch?vt6qBKPubEEo github: https://github.com/Mooler0410/LLMsPracticalGuide 来自这篇survey,但据说还在更新,到…

王道汽车4S企业管理系统 SQL注入漏洞复现

0x01 产品简介 王道汽车4S企业管理系统(以下简称“王道4S系统”)是一套专门为汽车销售和维修服务企业开发的管理软件。该系统是博士德软件公司集10余年汽车行业管理软件研发经验之大成,精心打造的最新一代汽车4S企业管理解决方案。 0x02 漏洞概述 王道汽车4S企业管理系统…

etcd相关知识整理归纳 —— 筑梦之路

什么是etcd? Etcd 是 CoreOS 团队于2013年6月发起的开源项目,它的目标是构建一个高可用的分布式键值(key-value)数据库。etcd内部采用raft协议作为一致性算法,Etcd基于 Go 语言实现。 名字由来,它源于两个方面,unix的“/etc”文件…

【ARM 裸机】汇编 led 驱动之编译程序

编译程序这一节分为四个步骤: 1、将 .s .c 文件变成 .o 文件,使用 arm-linux-gnueabihf-gcc; arm-linux-gnueabihf-gcc -g -c leds.s -o led.o上述命令就是将 leds.s 编译为 led.o,其中“ -g ”选项是产生调试信息,G…

lua学习笔记19(面相对象学习的一点总结)

print("*****************************面相对象总结*******************************") object{} --实例化方法 function object:new()local obj{}self.__indexselfsetmetatable(obj,self)return obj end-------------------------如何new一个对象 function object:…

Redis入门(常用命令、spring-boot-starter-data-redis)

Redis redis是一个基于内存的key-value的结构数据库 启动: redis-server.exe redis.windows.conf 客户端链接:redis-cli.exe [-h 目标ip] [-p 端口] [-a 密码] 修改链接密码: 在redis.windows.conf中的requirepass 123456 常用的数据类…

事务隔离级别的无锁实现方式 -- MVCC

MVCC的全称是Multiversion Concurrency Control(多版本并发控制器),是一种事务隔离级别的无锁的实现方式,用于提高事务的并发性能,即事务隔离级别的一种底层实现方式。 在了解MVCC之前,我们先来回顾一些简单的知识点:…

leetCode刷题 27. 移除元素

目录 1.思路: 2.解题方法: 3.复杂度: 4.Code 题目: 给你一个数组 nums 和一个值 val,你需要 原地 移除所有数值等于 val 的元素,并返回移除后数组的新长度。 不要使用额外的数组空间,你必须…

商城系统必备营销功能——分销裂变

电商流量红利已经过去,现在的电商营销,重点在于私域用户,在于客户资源裂变。人们通过分销裂变挖掘客户资源,能降低获客成本,对于需要解决成本困扰的企业来说,确实是个不错的选择。今天,我们就来…

FFmpeg: 自实现ijkplayer播放器--09音频重采样输出

文章目录 流程图音视设备输出回调函数重采样写入音频流因SDL输出音频采样格式为S16(一个采样点2个字节),而音频解码后采样格式通常为float planar(一个采样点4个字节),故需要重采样 重采样的条件:音频解码后的任意一个参数和需要的参数不同时,进行重采样,参数为: 采样格…

Nginx健康检查

Nginx健康检查nginx_upstream_check_module nginx健康检查介绍: ​ 主动健康检查,nignx定时主动地去ping后端的服务列表,当发现某服务出现异常时,把该服务从健康列表中移除,当发现某服务恢复时,又能够将该服务加回健…

Java并发--内存结构图及线程安全

内存结构图 内存-> (开辟的数组) -> (方法区,堆,栈,程序计数器,本地方法栈) 堆:几乎所有的对象实例都在这里分配内存。堆中每个对象的头信息都标属着他属于哪个类。 方法区它用于存储已被虚拟机加载的类型信息…

牛客_左右最值最大差_C++题解

原题链接:牛客 题目缩写:给你一个数组,由你来进行一个切分,分为两份,每份至少有1个元素;你分出来的这两个区间中各自有一个最大值,两者之差再求绝对值就是答案,这个答案越大越好&am…

认识异常(2)

❤️❤️前言~🥳🎉🎉🎉 hellohello~,大家好💕💕,这里是E绵绵呀✋✋ ,如果觉得这篇文章还不错的话还请点赞❤️❤️收藏💞 💞 关注💥&a…