jvm知识梳理

2023-10-27

1.java虚拟机的组成

java虚拟机主要由四部分组成

(1)ClassLoader:按特定格式加载class文件到内存中

(2)runtime data area:jvm内存空间模型

(3)execution engine:命令解析器

(4)native interface:融合不同开发语言的原生库供java使用

2.类加载过程

(1)编译器把.java文件编译成.class文件

(2)ClassLoader将.class文件加载到内存中,生成class<T>对象

(3)jvm根据class<T>生成对应的实体类对象

3.谈谈ClassLoader

ClassLoader负责将系统外部的class二进制数据流加载到jvm中,再由jvm进行连接/初始化。ClassLoader是一个抽象类,通过loadClass()方法加载类,ClassLoader的一般实现类有四个,即

(1)BootStrapClassLoader:由C++编写的基础类加载器,用于加载java.*下的核心类,加载路径是jre\lib\rt.jar或者系统变量Xbootclasspath下的类。源码不可见

(2)ExtClassLoader:由java编写的用于加载java扩展类javax.*下的类,加载路径是jre\ext\*.jar或系统变量Djava.ext.dirs下的类。 可以查看源码

(3)AppClassLoader:由java编写,用于加载工程目录下的类,加载路径是CLASSPATH或系统变量Djava.class.path下的类。 可以查看源码

(4)自定义ClassLoader:用户自己编写的(需继承ClassLoader),定制加载

4.双亲委派机制

在加载一个类时,步骤如下:

先判断此类是否已被加载,已加载则直接返回,未加载则从下至上继续判断

(1)判断是否已被自定义ClassLoader加载

(2)若未被自定义ClassLoader加载,则判断是否被AppClassLoader加载

(3)若未被AppClassLoader加载,则判断是否被ExtClassLoader加载

(4)若未被ExtClassLoader加载,则判断是否被BootStrapClassLoader加载

若全部加载器判断完,均未加载此类则由BootStrapClassLoader开始从上至下尝试加载

(1)尝试通过BootStrapClassLoader加载

(2)若未能被BootStrapClassLoader加载,则尝试通过ExtClassLoader加载

(3)若未能被ExtClassLoader加载,则尝试通过AppClassLoader加载

(4)若未能被AppClassLoader加载,则尝试通过ClassLoader加载

(5)若所有加载器都未能成功加载,抛出classNotFound异常

5.loadClass和forName区别

先说下类装载和加载的基础知识,类的加载分为隐式加载(new)和显式加载(loadClass和forName),java类的装载过程分为三个阶段。

(1)加载:通过ClasLoader加载class字节码文件,生成class对象

(2)连接:连接分为三个子步骤1校验,校验class文件的正确性和安全性。2准备,为类变量分配存储空间并设置初始值(注意:这里说的类变量是static类型变量,初始值是默认值,比如变量static int a = 111,在此步骤只给赋值0,因为int默认为0,111是在下一步赋值的)。3解析,将jvm常量池中的符号引用转为直接引用。

(3)初始化:进行类变量的复赋值和执行静态代码块

loadClass方法只是实现了上诉第一步,即加载

forName方法实现了全部三个步骤

6.JVM内存模型(jdk8)

由线程私有的:本地方法栈,虚拟机栈,程序计数器

线程公有的:元空间,堆

5部分组成,如图

(1)程序计数器:标识字节码文件执行行号,告诉机器执行哪行代码

(2)虚拟机栈:是java方法执行的内存模型,程序运行时每执行一个方法内存就会分配一定空间作为栈帧(Stack Frame是用于支持虚拟机进行方法调用和方法执行的数据结构),这些栈帧存放在虚拟机栈中,方法执行结束会自动按后进先出的策略释放这些栈帧,因此无需回收。栈帧由局部变量表和操作数栈组成,局部表量表存放方法中的各种局部变量,操作数占是描述方法执行中变量的计算/赋值过程

(3)本地方法栈:与虚拟机栈类似,只不过是针对native方法的栈

(4)元空间:存储class相关信息(class的方法,属性信息等)jdk7及以前,这部分属于永久代,元空间和永久代的本质区别是元空间使用本地内存,永久代使用jvm内存,使用元空间替代永久代有以下如下好处:消灭了outOfMerroryError:permGen space这个异常,之前永久代放在堆中,增加了GC的复杂度,而且类和方法信息大小难以确定,不方便指定永久代大小,永久代设置过大容易造成老年代内存溢出,永久代设置过小容易造成永久代内存溢出。再一点就是orcale有意将hotspot虚拟机和其他JVM集成,但永久代是hotspot特有的,为了方便后续集成去掉永久代

(5)堆:对象实例空间和GC管理的空间

7.为什么递归容易导致stackoverflow

因为调用方法会创建栈针并压如虚拟机栈,递归会不断创建栈针增加栈的深度,而线程的虚拟机栈深度固定,超出就会导致栈溢出

8.JVM核心参数

-Xms:堆的初始值

-Xmx:堆的最大值,在堆内存不足时,会自动扩容至-Xmx的大小,在实际中通常把此值设跟-Xms一样大,因为java堆扩容会发生内存抖动,非常影响机器的稳定性

-Xss:线程虚拟机栈大小,通常256K就够了,此参数影响并发线程数的大

-XX:NewRatio:老年代和年轻代内存大小比例,通常为2,即老年代和年轻代大小比例2:1

9.程序运行时的内存分配策略

静态存储:编译时即能确定运行时的存储空间需求(对应方法区,存class对象,类的static变量)

栈式存储:编译时不能确定,但运行时通过程序入口可确定的存储需求(对应栈,存和方法中的基本类型变量和对象类型的引用)

堆式存储:编译和运行时程序入口都不能确定空间的存储需求(对应堆,存new出来的对象类型)

10.栈和堆的联系和区别

联系:访问对象/数组时,会在栈中创建一个引用变量指向堆中对象/数组,退出方法时引用变量销毁但堆中对象仍然存在,堆中对象若一定时间内没有被引用变量指向则会被回收

区别:1.栈比堆小 2.栈自动释放堆需要GC 3.栈产生的碎片小于堆 4.栈支持静态分配和动态分配,堆只支持动态分配 5.栈的效率比堆高

11.谈谈String的intern方法在jdk6和jdk6以后的区别

方法作用:返回字符串在常量池中地址并赋给调用该方法的对象。

jdk6实现:从字符串常量池中查找,若不存在则在常量池中创建并返回

jdk6以后实现:从字符串常量池中查找,若不存在则进入堆中查找,若堆中存在则在常量池中创建该对象的引用并返回,若堆中也不存则在常量池中穿件并返回

引申练习题:请问下面两段代码输出结果是啥?

String s1=new String("a")+new String("b");
s1.intern();
String s2 = "ab";
System.out.println(s1==s2);//jdk6:false jdk7/jdk8:true
------------------------------------------
String s3=new String("a")+new String("b");
String s4 = "ab";
s1.intern();
System.out.println(s3==s4);//false
------------------------------------------
String s5=new String("a");
s1.intern();
String s6 = "a";
System.out.println(s5==s6);//false

12.GC的标记算法

(1)引用计数法:原理是记录对象被引用的次数,被一个对象引用则计数+1,引用被回收则-1,归0后被回收。优点是计算简单效率高,缺点是无法计算互相引用等场景

(2)可达性分析算法:判断程序中对象的引用链,当对象顺着引用链可被查到时,则认为“可达”,否则将被回收

13.GC的回收算法

(1)标记-清除算法:标记可达的对象,在回收时回收未标记的对象,优点效率高,缺点容易产生内存碎片

(2)标记-整理算法:标记可达的对象,在回收时将可达对象移动到集中的内存区域再进行回收,有点是相比标记清除算法解决了内存碎片的问题,但效率不如标记清除算法

(3)复制算法:将内存分为相等的两块区域,将可达对象标记后复制到另一块区域,然后全量清除原区域空间,优点是避免内存碎片问题,缺点是需要冗余一份内存空间,可达对象越少,采用复制算法越高效,因为复制对象会消耗cpu

(4)分代收集算法:是上诉算法的组合拳,把JVM分为年轻代和老年代,年轻代采取复制算法,老年代采取标记清除/整理算法

年轻代:执行minor GC,分为Eden区和Survivor区(Eden区是大部分对象创建时所在区域,除非内存很大的对象会被直接创建到老年代,Survivor区又分为from区和to区,这三个区的默认大小比例是8:1:1可在jvm参数-XX:SurvivorRatio设置Eden区和Survivor的比例),采用复制算法,具体执行过程为

第一步:标记Eden区和from区中可达对象

第二步:将上诉两区可达对象复制到to区,并将标记“年龄”加1,年龄超过15则存入老年代(15是默认,可在jvm参数-XX:+PretenuerSizeThreshold中配置)。当to区装不下复制结果时,也会将一部分对象直接放到老年代

第三步:将Eden区和from区清空,将原from区标记为下一次执行GC的to区,原to区反之

老年代:存放生命周期较长的对象,执行Full GC和Major GC,采用标记清除/标记整理算法

14.java中强引用,软引用,弱引用,虚引用的区别和作用

软引用:主要用途是做内存缓存,内存不足时回收,缓解内存不足导致OOM的问题

弱引用:比软引用更弱些,用于标记些偶尔使用的对象,会跟随GC被回收

虚引用:最弱的引用,用于跟随对象被垃圾回收器回收,哨兵作用

15.jvm两种运行模式

(1)Servier:启动较慢,但稳定运行后速度快

(2)Client:启动较快,但运行稳定后速度慢

16.垃圾收集器

(1)年轻代垃圾收集器

Serial收集器:采用复制算法,单线程收集,通过-XX:+UseSerialGC设置,此收集器简单高效,注重缩短stop-the-world的时间,提升用户体验,是Client模式下默认的年轻代收集器

ParNew收集器:Serial收集器的多线程版本(通过-XX:+UseParNewGC设置),特点与Serial收集器相同,在单核环境下效率不如Serial收集器,与Serial收集器是唯二的可以跟cms收集器共同工作的年轻代收集器,默认线程数是系统核数,可通过jvm参数修改

Parallel Scavenge收集器:通过-XX:+UseParallelGC设置,同样是多线程的采用复制算法的收集器,该收集器更注重提高系统吞吐量,适合后台跑定时任务之类的应用,是Server模式下默认的年轻代收集器

(2)老年代垃圾收集器

Serial Old收集器:采用标记-整理算法,单线程收集,通过-XX:UseSerialOldGC设置,Client模式下默认的老年代收集器,可搭配任何年轻代收集器使用

Patralled Old收集器:采用标记-整理算法,多线程收集,吞吐量优先,搭配年轻代的Parallel Scavenge使用,通过-XX:+UseParalledOldGC设置

CMS收集器:采用标记-清除算法,通过-XX:+UseConcMarkSweepGC设置,是常用的老年代收集器。

G1(Garbage First)收集器:同时用于年轻代和老年代,特点是会将整个java堆内存划分成多个大小相等的Regin,年轻代和老年代不再物理隔离

G1有如下优势:

1.并发和并行:G1可以用多个CPU来缩短stop-the-world

2.分代收集:虽然年轻代和老年代不再物理隔离,但仍然独立处理新对象和存活已久的老对象

3.空间整合:因为基于标记-整理算法,解决了很多其他老年代收集器内存不连续问题

4.可预测的停顿:因为支持配置垃圾收集所占用时间在N毫秒内

17.对象从年轻代晋升到老年代的场景

(1)对象过大,直接创建到老年代

(2)可达性算法计数年龄达到阈值(默认15)

(3)动态对象年龄判定:当 Survivor 空间中相同年龄所有对象的大小总和大于 Survivor 空间的一半,年龄大于或等于该年龄的对象就可以直接进入老年代,而不需要达到默认的分代年龄

18.触发full GC的条件

(1)老年代空间不足

(2)永久代(如有)空间不足

(3)gc 担保失败,逻辑如下图

(4)程序中的Sysyem.gc()

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

jvm知识梳理 的相关文章

随机推荐

  • 钉钉微应用开发调试

    1 下载安卓调试包 2 安卓手机点击 设置 开发者选项 USB调试 3 打开钉钉 设置 通用 开发者选项 微应用调试 4 手机连接到电脑 打开chrome chrome inspect 开始调试 如果chrome inspect显示错误页面
  • 超声波模块的使用

    C SR04超声波测距模块可提供约2cm400厘米的非接触式距离感测功能 测距精度可达高到3毫米 模块包括超声波发射器 接收器与控制电路像智能小车的测距以及转向 或是一些项目中 常常会用到 智能小车测距可以及时发现前方的障碍物 使智能小车可
  • 【Unity3D】在Unity中使用Protobuf(proto3)

    有研究表明 一条消息数据 用protobuf序列化后的大小是json的10分之一 xml格式的20分之一 是二进制序列化的10分之一 ProtoBuf的优势还是很明显的 这里简单介绍哈使用 一 下载protobuf https github
  • css移动端页面单位,移动端web开发PX单位问题

    在页面开发过程中 对于设计给的设计稿 一般的PC页面开发的时候 很简单 使用px为单位 给多少px就标注多少 但是到了移动端的web开发 一般标注的单位是dp 这对于css里面px单位就需要转换一下了 这边简单说明一下相关点 几个概念 设备
  • linux启动/重启mongo时报错$OPTIONS (code=exited, status=14)

    遇到过多次这个问题 在此记录一下 网上查了很多 但关于为什么原本好好的 mongo 会报此类错误的原因分析的文章并不多 目前发现 没有正确退出 mongo mongo 配置文件修改错误 修改 mongo 配置文件后重启 等 都有可能导致 m
  • shift用计算机,shift是什么意思_shift键有什么用? - 学无忧

    在我们的电脑键盘上有一个shift上档键 shift是什么意思 shift键有什么用 经常使用电脑的人都会用到这个shift键 这个键跟ctrl和atl键都是很常用的按键 学无忧就来针对shfit来具体讲解 shift是什么意思 shift
  • Mysql 联合索引最左匹配原则

    最左前缀匹配原则 在MySQL建立联合索引时会遵守最左前缀匹配原则 即最左优先 在检索数据时从联合索引的最左边开始匹配 Mysql会一直向右匹配直到遇到范围查询 gt lt between like 就停止匹配了 就比如 a 3 and b
  • 算法学习笔记:labuladong--滑动窗口

    算法技巧的思路非常简单 就是维护一个窗口 不断滑动 然后更新答案 int left 0 right 0 while right lt s size 增大窗口 window add s right right while window nee
  • Python中 sys.argv[]的用法简明解释

    因为是看书自学的python 开始后不久就遇到了这个引入的模块函数 且一直在IDLE上编辑了后运行 试图从结果发现它的用途 然而结果一直都是没结果 也在网上查了许多 但发现这个问题的比较详细的解释只有一个版本 大部分都是转载和复制的 给的都
  • 大数据入门学习

    https www cnblogs com xing901022 p 6195422 html
  • redis之list基本操作

    我们存多个数据用hash的时候它是没有顺序的 我们平时操作 实际上数据很多情况下都是有顺序的 那有没有一种能够用来存储带有顺序的这种数据模型呢 list就专门来干这事儿 一 list类型 数据存储需求 存储多个数据 并对数据进入存储空间的顺
  • 常用的两个免费可以商用的cc0协议图片网站

    什么是CC0协议CC0是CC协议 知识共享 是Creative Commons在中国大陆地区的通用译名 一般简称为CC CC既是该国际组织的名称缩写 也是一种版权授权协议的统称 以外的一种新的版权声明协议 采用该协议即代表作者宣布放弃该创作
  • ROS Noetic版本 rosdep找不到命令 不能使用的解决方法

    使用rosdep指令来安装开源包所需的依赖是很方便的 本文主要介绍ROS Noetic版本中使用rosdep 报错找不到命令 rosdep不能使用的解决方法 rosdep 找不到命令 Command rosdep not found but
  • nginx 中文url rewrite 404

    2019独角兽企业重金招聘Python工程师标准 gt gt gt 原料 nginx with debug或openresty 背景 项目中有用户图片库需求 允许用户自定义文件夹 然后上传图片到该文件夹 当用户自定义的文件夹为中文或者访问u
  • 微信第三方平台之代开发小程序(二)

    第二部分 快速创建小程序 必须全网发布成功 注 第一部分 全网发布前的准备 请看我前面的文章 1 权限集准备 全网发布成功后才可生效 2 第三方收集法人微信 法人姓名 企业名称 信用代码四个商户信息外加第三方客服电话 3 企业名称需与工商部
  • 【python教程入门学习】Python教程第1篇:下载和安装Python

    Python是当下流行的通用编程语言 简单易学 容易上手 且 钱 景广阔 在网络爬虫 数据挖掘分析 人工智能 运营运维 日常工作效率提升 无不有Python的影子 因此 今天跟大家分享Python的下载和安装教程 第一步 下载Python最
  • 域名服务详解(域名解析流程和分类)

    一 基本概念 访问互联网是依靠IP地址的 但IP地址多种多样 很难记忆 所以使用域名服务 代替IP地址输入 1 hosts文件 1 位置 Windows系统在C Windows System32 drivers etc hosts 需要超级
  • usdt充值btc网络(非节点钱包地址)

    1 此充值具有一定的交易风险 请一定做好判断 步骤 用户绑定其他交易所的地址 往平台充值 只能使用用户绑定的钱包地址充值 否则无法确认充值成功 用户先填写充值金额 gt 生成充值订单 gt 通过平台设置的收币钱包地址充值 gt 填写充值产生
  • ReactNative组件生命周期

    组件生命周期详解 组件生命周期基础知识 组件 又名控件 是一段独立可复用的代码 在React Native应用开发中 组件是页面最基本的组成部分 和React的组件一样 RN的组件也有自己的生命周期 在RN应用开发中 组件的生命周期指组件初
  • jvm知识梳理

    1 java虚拟机的组成 java虚拟机主要由四部分组成 1 ClassLoader 按特定格式加载class文件到内存中 2 runtime data area jvm内存空间模型 3 execution engine 命令解析器 4 n