JVM快速入门篇

news2024/11/26 13:52:18

一、JVM探究

1.1前言

  1. 请你谈谈你对jvm的理解?
  2. Java8虚拟机和之前的变化更新?
  3. 什么是OOM?什么是栈溢出StackOverFlowError?怎么分析?
  4. jvm的常见调优参数有哪些?
  5. 内存快照如何抓取?怎么分析Dump文件?
  6. 谈谈jvm中,类加载器你的认识?

1.2内容分派

1. JVM的位置
2. JVM的体系结构
3. 类加载器
4. 双亲委派机制
5. 沙箱安全机制
6. Native
7. PC寄存器
8. 方法区
9. 栈
10. 三种JVM
11. 堆
12. 新生区、老年区
13. 永久区
14. 堆内存调优
15. GC

  1. 常用算法

16. JMM 

二、 JVM位置

JVM(Java Virtual Machine)是 Java 虚拟机,用于运行 Java 编译后的二进制字节码,最后生成机器指令。JVM 是 Java 能够跨平台的核心。JDK : (Java Development Kit),Java 开发工具包。JDK 是整个 Java 开发的核心,集成了 JRE 和javac.exe,java.exe,jar.exe 等工具。JRE : (Java Runtime Environment),Java 运行时环境。主要包含两个部分,JVM 的标准实现和 Java 的一些基本类库。它相对于 JVM 来说,多出来的是一部分的 Java 类库。

JVM 与操作系统之间的关系: JVM 上承开发语言,下接操作系统,它的中间接口就是字节码。

因此,JVM 的位置取决于你安装了哪个 JDK 版本和你的操作系统。如果你使用 Windows 操作系统,则可以在 cmd 中输入 java -version 命令来查看 JDK 的安装位置。如果你使用 Linux 操作系统,则可以在终端中输入 which java 命令来查看 JDK 的安装位置。

3a1489d671cf4effbdeff9b216333a6f.png

三、JVM体系结构

3.1 jvm结构图

12336a185e8e44318a33f481a529039c.png

3.2 jvm垃圾回收

垃圾回收,指的的堆内存的垃圾回收

在 JVM 中,有一个垃圾回收线程,它是低优先级的,在正常情况下是不会执行的,只有在虚拟机空闲或者当前堆内存不足时,才会触发执行,扫描那些没有被任何引用的对象,并将它们添加到要回收的集合中,进行回收

JVM 的垃圾回收机制主要是针对堆内存消亡的对象的回收和内存分配。在 JVM 进行垃圾回收之前,首先就是判断哪些对象是垃圾,也就是说,要判断哪些对象是可以被销毁的,其占有的空间是可以被回收的

Java 的垃圾回收机制主要采用了引用计数法和可达性分析算法两种方式来判断哪些对象可以被销毁。其中引用计数法是为每个对象创建一个引用计数,有对象引用时计数器 +1,引用被释放时计数 -1,当计数器为 0 时就可以被回收。但是它有一个缺点是不能解决循环引用的问题。可达性分析算法则从 GC Roots 开始向下搜索,搜索所走过的路径称为引用链。当一个对象到 GC Roots 没有任何引用链相连时,则证明此对象是可以被回收的。

Java 的垃圾回收机制主要采用了四种垃圾回收算法:标记-清除算法、复制算法、标记-整理算法和分代算法。其中标记-清除算法效率不高,无法清除垃圾碎片;复制算法内存使用率不高;标记-整理算法效率较高;分代算法则根据对象存活周期的不同将内存划分为几块,一般包括年轻代、老年代和永久代。 844319e9d3eb428b91a16ce6295600e4.png

3.3 jvm调优

JVM调优,99%是调堆

JVM 调优的目的是追求更低的系统延迟和更高的系统吞吐量,衡量系统在稳定状态下所需要的最低内存占用量。JVM 调优主要是针对垃圾收集器的收集性能优化,令运行在虚拟机上的应用能够使用更少的内存以及延迟获取更大的吞吐量

JVM 调优一般包含多个层次,比如:架构调优、代码调优、JVM 调优、数据库调优、操作系统调优等。其中架构调优和代码调优是 JVM 调优的基础,架构调优是对系统影响最大的

JVM 调优主要是通过不断测试调整 JVM 的运行参数,尽可能让对象都在新生代 (Eden) 里分配和回收,尽量别让太多对象频繁进入老年代,避免频繁对老年代进行垃圾回收,同时给系统充足的内存大小,避免新生代频繁的进行垃圾回收

4ce76b5080ce4ebda946994c0f30644b.png

四、类加载器

加载Class文件

4.1类加载的过程

eaf7adfecc894c8f93c8c91befb02b9b.png

4.2哪些类加载器

  1. 引导类加载器(BootstrapClassloader):用C++编写,是JVM自带的类加载器;负责加载Java的核心类库。(该加载器无法直接获取)
  2. 扩展类加载器(ExtClassloader):负责加载/jre/lib/ext目录下的jar包。
  3. 应用程序类加载器(AppClassloader):负责加载java -classpath或-D java.class.path所指的目录下的类与jar包。(最常用的加载器)

4.3双亲委派机制

  1. 类加载器接收到一个加载请求时,他会委派给他的父加载器,实际上是去他父加载器的缓存中去查找是否有该类,如果有就加载返回,如果没有则继续委派给父类加载,直到顶层类加载器。
  2. 如果顶层类加载器也没有加载该类,则会依次向下查找子加载器的加载路径,如果有就加载返回,如果都没有,则会抛出异常。
  3. 这种工作机制可以保证Java核心库的类型安全,防止用户自己编写的同名类被优先加载,从而确保Java程序的稳定运行

 五、 沙箱安全机制

Java沙箱安全机制是一种用于保护Java代码和本地系统之间的安全技术,它可以限制Java代码对本地资源的访问,防止其造成潜在的危害。Java沙箱安全机制的发展经历了几个阶段,从最初的完全隔离到后来的可配置的权限控制,以及引入了代码签名、域和安全管理器等概念。Java沙箱安全机制的基本组件包括字节码校验器、类加载器、存取控制器、安全管理器和安全软件包等

 六、native、方法区

6.1native

凡是使用了native关键字的,说明Java的作用范围已经达不到了,它会去调用底层的C语言的库。

  1. 进入本地方法栈。
  2. 调用本地方法接口。JNI

JNI的作用:扩展Java的使用,融合不同的语言为Java所用。(最初是为了融合C、C++语言)

因为Java诞生的时候,C和C++非常火,想要立足,就有必要调用C、C++的程序。

所以Java在JVM内存区域专门开辟了一块标记区域Native Method Area Stack,用来登记native方法。
在最终执行(执行引擎执行)的时候,通过JNI来加载本地方法库中的方法。

98644debff5c4f0eab77a07c27c1df06.png 6.2PC寄存器

程序计数器:Program Counter Register
每个线程都有一个程序计数器,是线程私有的,就是一个指针,指向方法区中的方法字节码(用来存储指向像一条指令的地址,也即将要执行的指令代码),在执行引擎读取下一条指令,是一个非常小的内存空间,几乎可以忽略不计。

6.3方法区

Method Area方法区(此区域属于共享区间,所有定义的方法的信息都保存在该区域)
方法区是被所有线程共享,所有字段、方法字节码、以及一些特殊方法(如构造函数,接口代码)也在此定义。

静态变量,常量、类信息(构造方法、接口定义)、运行时的常量池存在方法区中但是实例变量存在堆内存中,和方法区无关

static final, Class, 常量池

 七、栈(后进先出)

7.1栈的作用

栈内存,主管程序的运行,生命周期和线程同步;
线程结束,栈内存也就释放了,对于栈来说,不存在垃圾回收问题

7.2栈存储的东西

8大基本类型、对象引用,实例的方法。 

7.3 栈运行原理

7.3.1简单结构图

ade25707763d43848164205b0715c995.png

7.3.2详细结构图

2a63752f24724d3d8e8e3f3750d1eedf.png 7.3.3栈+堆+方法区的交互关系

9cf099d5df864017bd2b36246244ff73.png

八、堆

8.1三种JVM

  1. Sun公司的HotSpot。(java -version查看)
  2. BEA的JRockit
  3. IBM的J9VM

8.2. 堆

Heap,一个JVM只有一个堆内存,堆内存的大小是可以调节的。

类加载器读取了类文件后,一般会把什么东西放到堆中?
类、方法、常量、变量、保存我们所有引用类型的真实对象。

堆内存中细分为三个区域:

  • 新生区(伊甸园区)Young/New
  • 养老区 old
  • 永久区 Perm

5eae7c01d91d48bba84356367812abf7.png

8.3新生区

新生区又叫做伊甸园区,包括:伊甸园区、幸存0区、幸存1区。

8.4永久区

这个区域是常驻内存的。
用来存放JDK自身携带的Class对象、Interface元数据,存储的是Java运行时的一些环境或类信息~。
这个区域不存在垃圾回收
关闭JVM虚拟机就会释放这个区域的内存。

什么情况下,在永久区就崩了?

  • 一个启动类,加载了大量的第三方jar包。
  • Tomcat部署了太多的应用。
  • 大量动态生成的反射类;不断的被加载,直到内存满,就会出现OOM

8.5永久代和元空间 

这个区域常驻内存的。用来存放JDK自身携带的Class对象。Interface元数据 ,存储的是ava运行时的一些环境或类信息

什么是永久代和元空间??
方法区是一种规范,不同的虚拟机厂商可以基于规范做出不同的实现,永久代和元空间就是出于不同jdk版本的实现。
方法区就像是一个接口,永久代与元空间分别是两个不同的实现类。
只不过永久代是这个接口最初的实现类,后来这个接口一直进行变更,直到最后彻底废弃这个实现类,由新实现类—元空间进行替代。

jdk1.8之前:

43c43d5e9b1f4013a720be5628713ecd.png

jdk1.8以及之后:在堆内存中,逻辑上存在,物理上不存在(元空间使用的是本地内存)321302daa0b64e2fa0897c98df007e2a.png 

九、使用JProfiler工具分析OOM原因

Java OOM异常通常是由于内存泄漏或者内存溢出导致的。内存泄漏指的是程序中已经不再使用的对象仍然被引用,导致垃圾回收器无法回收,最终导致内存溢出。而内存溢出则是指程序在申请内存时,没有足够的空间供其使用,最终导致程序崩溃

Java OOM异常通常有以下几种原因:

  • Java堆用于存储对象实例,只要不断地创建对象,并且保证GC Roots到对象之间有可达路径来避免垃圾回收机制清除这些对象,那么在对象数量到达最大堆的容量限制后就会产生内存溢出异常。
  • 无法在Java堆中分配对象。
  • 应用程序保存了无法被GC回收的对象。
  • 应用程序过度使用finalizer。

b9f672f12df941cb860b6ddec7ac5aa4.png

十、GC垃圾回收

 10.1垃圾回收的区域

24b7889a917c4499b97fdaf46b88ecf4.png

10.2GC之引用计数法

798b27ea3ef641ad9c72e3f384367fea.png10.3GC之复制算法

833282e7f57a4479aec85406d66cab61.png

8e89cc5bb1664607bd3cd85b0c8976da.png

 好处:没有内存的碎片。

坏处:浪费了内存空间(多了一半空间to永远是空)。假设对象100%存活(极端情况),不适合使用复制算法。

使用场景

复制算法最佳使用场景:对象存活度较低的时候(新生区)

10.4 GC之标记清除压缩算法

10.4.1 标记清除

  • 优点:不需要额外的空间。
  • 缺点:两次扫描,严重浪费时间,会产生内存碎片。

10.4.2标记清除压缩

 标记清除压缩(改进)

 标记清除压缩(改进)

10.4.3 标记清除压缩(改进)

内存效率:复制算法>标记清除算法>标记压缩算法(时间复杂度)
内存整齐度:复制算法=标记压缩算法>标记清除算法
内存利用率:标记压缩算法=标记清除算法>复制算法

思考一个问题:难道没有最优算法吗?
答案:没有,没有最好的算法,只有最合适的算法——》GC:分代收集算法

年轻代:

  • 存活率低
  • 复制算法

老年代:

  • 区域大:存活率高
  • 标记清除(内存碎片不是太多)+标记压缩混合实现

十一、JMM是什么

11.1JMM是什么

JMM(Java Memory Model),Java的内存模型。

11.2 JMM的作用

缓存一致性的协议,用来定义数据读写的规则。

JMM定义了线程工作内存和主内存的抽象关系:线程的共享变量存储在主内存中,每个线程都有一个私有的本地工作内存。

使用volatile关键字来解决共享变量的可见性的问题。

Java内存模型是围绕着并发编程中原子性、可见性、有序性这三个特征来建立的。

11.3JMM的操作

a498ab2e53f7467eaf017c11e86f46a9.png

JMM定义了8种操作来完成(每一种操作都是原子的、不可再拆分的)。

  • lock(锁定):作用于主内存的变量,它把一个变量标识为一条线程独占的状态。
  • unlock(解锁):作用于主内存的变量,它把一个处于锁定状态的变量释放出来,释放后的变量才可以被其他线程锁定。
  • read(读取):作用于主内存的变量,它把一个变量的值从主内存传输到线程的工作内存中,以便随后的load动作使用。
  • load(载入):作用于工作内存的变量,它把read操作从主内存中得到的变量值放入工作内存的变量副本中。
  • use(使用):作用于工作内存的变量,它把工作内存中一个变量的值传递给执行引擎(每当虚拟机遇到一个需要使用到该变量的值的字节码指令时将会执行这个操作)。
  • assign(赋值):作用于工作内存的变量,它把一个从执行引擎接收到的值赋给工作内存的变量(每当虚拟机遇到一个给该变量赋值的字节码指令时执行这个操作)。
  • store(存储):作用于工作内存的变量,它把工作内存中一个变量的值传送到主内存中,以便随后的write操作使用。
  • write(写入):作用于主内存的变量,它把store操作从工作内存中得到的变量的值放入主内存的变量中。

11.4并发编程的三大特性

1. 原子性

一个或多个程序指令,要么全部正确执行完毕不能被打断,或者全部不执行

2. 可见性

当一个线程修改了某个共享变量的值,其它线程应当能够立即看到修改后的值。

3. 有序性

程序执行代码指令的顺序应当保证按照程序指定的顺序执行,即便是编译优化,也应当保证程序源语一致。

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

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

相关文章

RichView Text Box Items 文本框

RichView Text Box Items 文本框 RichView的文本框(Text Box),是TRichView文档中的ITEM之一。 通常文本框项目(Text Box Item)是旁注的简化版本,该项目插入的位置没有可见的文本。 如果rvoShowSpecialChara…

【数学建模竞赛】数据预处理知识总结1——数据清洗

数据预处理是什么 在数学建模赛题中,官方给所有参赛选手的数据可能受到主观或客观条件的影响有一定的问题,如果不进行数据的处理而直接使用的话可能对最终的结果造成一定的影响,因此为了保证数据的真实性和建模结果的可靠性,需要…

中频炉冷循环监测终端,智能化管理冷却系统的新利器!

在现代工业生产中,中频炉是一种广泛应用于金属加工和熔化的设备。 一、中频炉的降温剂 中频炉的使用中,企业往往关注的是中频炉晶闸管、电抗器、电容器、汇流排以及中频炉线圈,忽观中频炉的冷却水。中频炉的冷却水在中频炉、中频加热炉使用…

ICC2:partial blockage array脚本

我正在「拾陆楼」和朋友们讨论有趣的话题,你⼀起来吧? 拾陆楼知识星球入口 用法是先在玩加partial blockage array的地方create一个blockage,然后选中source这个脚本。需要定义三个值,分别是blockage的百分比,还有每个组成阵列的每个blockage宽和高。 addHBlkForSpecAre…

【以太网硬件二十一】USXGMII是什么?-Part2

👉个人主页: highman110 👉作者简介:一名硬件工程师,持续学习,不断记录,保持思考,输出干货内容 目录 PCS功能细节 XGMII到USXGMII的映射 带内配置和状态信号 自协商相关 电气特…

如何修复老照片?老照片修复翻新的方法

老旧照片,尤其是黑白照片,往往因为年代久远、保存方式不当等原因而出现褪色、污损、划痕等问题,会比较难以修复,就算是技术精湛的专业修复师,也是需要投入极大时间精力的,效果也是不可预料的。 修复老照片…

YOLOv5添加注意力机制

添加SE注意力机制 第一步 添加代码-SE类-models/common.py第二步 添加注意力关键词-models/yolo.py第三步 创建配置文件-models/yolov5s_SE.yaml第四步 修改读取配置-train.py 第一步 添加代码-SE类-models/common.py 进入models/common.py文件,这个文件里面包含了…

直线导轨的替换方法

目前,直线导轨的使用率持续上升,已广泛应用在各种各样的行业中,可替换性高是其广泛使用的重要原因之一!直线导轨的替换指的就是导轨和滑块可以单出,不用整套替换。 市面上使用率最高的直线导轨品牌应该就是台湾*银了&a…

利用python进行视频下载并界面播放快速下载素材

工具:python designer(python自带):UI界面设计工具 VLC:视频播放工具 需要的库如下: import os,platform os.environ[PYTHON_VLC_MODULE_PATH] "./vlc-3.0.14" import vlc from 脚本 import Player from …

Effective Java(中文版第3版)第2条:遇到多个构造器参数时要考虑使用构建器

Effective Java(中文版第3版)第2条:遇到多个构造器参数时要考虑使用构建器

Unity(三) Shader着色器初探

学习3D开发技术的时候无可避免的要接触到Shader,那么Shader是个什么概念呢?其实对于开发同事来说还是比较难理解的,一般来说Shader是服务于图形渲染的一类技术,开发人员可以通过其shader语言来自定义显卡渲染页面的算法&#xff0…

MyBatis-快速入门

MyBatis是一款优秀的持久层框架,用于简化JDBC的开发 MyBatis是Apache的一个开源项目iBatis,2010年这个项目由apache迁移到了Google code,并且改名为MyBatis,2013年11月迁移到Github 使用MyBatis查询所有用户信息: 1.准备工作&a…

项目管理工具:实现项目科学管理的利器

什么是项目管理工具 项目管理工具是指用于协助规划、组织、执行和监控项目活动的软件或应用程序。它们提供了一系列功能和工具,帮助项目管理人员和团队有效地管理项目进度、资源分配、任务协作以及沟通等方面的工作。项目管理工具的目标是提高团队的工作效率、优化…

Git 基本原理和常用操作

Git Git 是一个开源的分布式版本控制系统,可以有效、高速地处理从很小到非常大的项目版本管理。由 Linus Torvalds 为了帮助管理 Linux 内核开发而开发的一个开源的版本控制软件。 Git 常用操作 git 提交流程:工作区 -> git add 到暂存区 -> gi…

RunnerGo——更高效、更易用的性能测试利器

随着互联网技术的迅速发展,性能测试已成为保障应用程序顺畅运行的关键环节。在众多性能测试工具中,RunnerGo以其独特的优势,逐渐成为了开发者和测试人员的首选。本文将详细介绍RunnerGo的特点,并对比其与JMeter的优势,…

mac开机启动项怎么设置,MAC系统启动项怎么更改

一些软件在安装的时候可能会自动添加开机启动项,如果觉得影响开机速度或者不再需要了该怎么删除开机启动项呢?如何添加删除MacBook的开机启动项。下面小编教大家如何设置开机启动项。 第一步:点击左上角苹果标识下拉菜单进入系统偏好设置 第…

优雅编码!Java与MongoDB的创新数据库架构

随着现代应用程序对数据存储和处理需求的不断增加,开发人员需要寻找更具创新性和灵活性的数据库架构来满足这些需求。在这样的背景下,Java与MongoDB的结合为开发人员提供了一种创新的数据库架构,为应用程序带来了无限可能。下面将探讨Java与M…

万宾毫米波水位监测仪:实时监测河湖水位

河湖是人类生存和发展的重要自然资源,保障其安全运行是维护社会稳定和生态平衡的重要任务。随着经济的发展和人口的增加,对水资源的需求日益增长,但同时也面临着洪水和干旱等自然灾害的威胁。因此,对河湖进行监测成为了至关重要的…

个人博客项目测试报告

目录 一. 项目背景 二. 概述 三. 功能测试用例 四. 自动化测试用例 一. 项目背景 项目链接: http://81.70.189.104:8080/login.html 个人博客系统提供了 登录、注册、写博客&发布博客、删除博客、修改博客功能。前端的页面有 登录页、注册页、个人博客列表页、博客详情…

使用docker容器内的anaconda虚拟环境启动python web项目

1、环境安装 1.1 基础镜像 这里以ubuntu18.04 cuda 11.8为基础镜像(主机支持nvidia-gpu) (1)拉取ubuntu18.4 cuda11.8镜像 docker pull nvidia/cuda:11.8.0-devel-ubuntu18.04 1.2 docker下anaconda安装 (1&am…