JVM探究

news2024/11/15 10:13:55

JVM探究

  • 请谈谈你对JVM的理解?java8虚拟机和之前的变化、更新?
  • 什么是OOM,栈溢出StackOverFlowError?怎么分析?
  • JVM的常用调优参数有哪些?
  • 内存快照如何 抓取,怎么分析Dump文件?知道吗?
  • 谈谈JVM中,类加载器你的认识?(rt-jar ext application)
  1. JVM的位置

  2. JVM的体系结构

  3. 类加载器

  4. 双亲委派机制

  5. 沙箱安全机制

  6. Native

  7. PC寄存器

  8. 方法取

  9. 三种JVM

  10. 新生区、老年区

  11. 永久区

  12. 堆内存调优

  13. GC

    常用算法

  14. JMM

  15. 总结

一、JVM的位置

JVM就是一个虚拟机软件,

操作系统也是一个软件

image.png

二、JVM的体系结构

image.png

Java栈、本地方法栈和程序计数器不会有垃圾。

image-20230627104245800.png

JVM调优99%都是在调堆

image.png

三、类加载器

image.png

类加载器分类:会倒着一层一层往上找APP---->EXC---->BOOT(最终执行)

  1. 虚拟机自带的加载器
  2. 启动类(根)加载器
  3. 扩展类加载器
  4. 应用程序加载器

image.png

四、双亲委派机制

双亲委派机制:是安全的

java.lang文件夹下的东西一本不能动!

双亲委派机制的步骤:

  1. 类加载器收到类加载的请求
  2. 将这个请求向上委托给父类加载器去完成,一直向上委托,直到启动类加载器
  3. 启动加载器检查是否能够加在当前这个类,能记载就结束,使用当前的加载器,否则,抛出异常,通知子加载器进行加载
  4. 重复步骤 3

classLoader获取不到出现null,因为 :java 调用不到~,C、C++

五、native、PC寄存器、方法区

native:核心

JNI 本地方法接口:Java native Interface

凡是带了native关键字的,说明java的作用范围达不到了,会去调用底层C语言的库!会进入本地方法栈。

JNI 作用:扩展 Java的使用,融合不同的编程语言为Java所用! 最初:C、C++

Java诞生的时候,C、C++横行,想要立足,必须要有调用C、C++的程序~

它在内存区域中专门开辟了一块标记区域:Native Method Stack,登记 native 方法

在最终执行的时候,加载本地方法库中的方法通过 JNI

程序计数器:Program Counter Register

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

方法区 Method Aera

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

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

static final Class 常量池

六、栈

栈:先进后出,后进先出

队列:先进先出(FIFO:First Input First Output)

为什么 main()先执行,最后结束~(因为方法放在栈中,最先入栈的最后出栈)

栈:别名“栈内存”,主管程序的运行,声明周期和线程同步;

线程结束,占内存也就释放,对于栈来说,不存在垃圾回收问题

一旦线程结束,栈就Over!

栈中存放的有:8大基本类型 + 对象引用 + 实例的方法

8大基本类型:byte short int long float double char boolean

  • 逻辑类型:boolean
  • 整数类型:byte short int long
  • 浮点类型:float double
  • 字符类型:char

栈运行原理:栈帧(相当于一片一片的)

栈顶、栈底

黑色是栈,浅绿色是栈顶,黄色是栈底

父帧、子帧:

栈满了,会抛出 StackOverflowError

image.png

栈 + 堆 + 方法区:交互关系

image.png

七、三种JVM

使用 java -version 命令就可以查看

  • Sun:HotSpot(99%)
  • BEA:JRockit
  • IBM:J9VM

我们学习都是: HotSpot

八、堆

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

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

堆内存还要细分为三个区域:

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

image.png

GC垃圾回收主要是在新生区和养老区,更详细是伊甸园和养老区~

假设内存满了,OOM,堆内存不够!java.lang.OutOfMemoryError:Java heap space

在 JDK8以后,永久存储区改了一个名字(元空间)

image.png

新生区
  • 是 类:诞生 和 成长的地方,甚至死亡;
  • 伊甸园,所有的对象都是在 伊甸园区 new 出来的!
  • 幸存者区(0,1)
永久区

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

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

  • jkd1.6之前:永久代,常量池是在方法区;

  • jkd1.7 :永久代,但是慢慢的退化了,去永久代,常量池在堆中;

  • jkd1.8之后:无永久代,常量池在元空间

jkd1.8之后的堆内存结构示意图:

image.png

元空间逻辑上存在,物理上不存在~(因为不会占用内存)

在一个项目中,突然出现了OOM故障,那么该如何排除~研究为什么出错?

  • 能够看到代码第几行出错:内存快照分析工具,MAT,Jprofiler
  • Debug,一行行分析代码!:公司基本没有这样的条件去一行行debug

使用MAT,Jprofiler的作用:

  • 分析Dump内存文件,快速定位内存泄露;
  • 获得堆中的数据
  • 获得大的对象

设置最大内存和总内存的命令:

-Xms1024 -Xmx1024m -XX:+PrintGCDetails  //打印GC垃圾回收信息

-Xms:设置初始化内存分配大小  默认 1/64
-Xmx:设置最大分配内存       默认 1/4

-Xms1m -Xmx8m -XX:+HeapOnOutOfMemoryError  //oom Dump, 需要 Dump 错误的命令;命令含义:当堆Heap在报 OutOfMemoryError 时 Dump 下来

如何 排 OOM 错?

  1. 尝试扩大堆内存看结果
  2. 分析内存,看一下哪个地方出现了问题(使用Jproflie专业分析快照工具)

个人写的杂乱笔记:

package cs20230625;

/**
 * @author: Arbicoral
 * @create: 2023-06-25 19:24
 * @Description: 跟着狂神的JVM
 *
 * 需要 Dump 错误的命令:-Xms1m -Xmx8m -XX:+HeapOnOutOfMemoryError  //oom Dump
 * 当堆Heap在报 OutOfMemoryError 时 Dump 下来
 * -Xms:设置初始化内存分配大小  默认 1/64
 * -Xmx:设置最大分配内存       默认 1/4
 * -XX:+PrintGCDetails
 */
public class Demo {
    public static void main(String[] args) {
        long totalMemory = Runtime.getRuntime().totalMemory();
        long maxMemory = Runtime.getRuntime().maxMemory();

        System.out.println("max = " + maxMemory+"字节\t" + (maxMemory/(double)1024/1024) + "MB");
        System.out.println("total = " + totalMemory+"字节\t" + (totalMemory/(double)1024/1024) + "MB");

        //默认情况下:分配的总内存是 电脑内存的 1/4,而初始化内存 1/64
        //OOM:
            //1. 尝试扩大堆内存看结果
            //2. 分析内存,看一下哪个地方出现了问题(使用Jproflie专业分析快照工具)
        //-Xms1024 -Xmx1024m -XX:+PrintGCDetails  //打印GC垃圾回收信息
    }
}

九、GC垃圾回收

GC的作用区域:

image.png

JVM在进行 GC时,并不是对这三个区域统一回收。大部分时候,回收都是新生代~

  • 新生代

  • 幸存区(from,to)

  • 老年区

    GC两种类型:轻GC(普通的GC),重GC(全局GC 或 Full GC)

GC题目:

  • JVM的内存模型和分区~详细到每个区放什么?
  • 堆里面的分区有哪些? Eden, from , to, 老年区,永久区(元空间),说说他们的特点
  • GC的算法有哪些?标记清除法,标记压缩,复制算法,引用计数器,怎么用的?
  • 轻GC 和 重GC 分别在什么时候发生?

引用计数法

有一个专门负责计数的空间,当计数器发现对象引用为0就会被清理掉;

计数器本身也会有消耗(python用的就是这个)

image.png

复制算法

谁空谁是to

当一个对象经历了15次GC,都还没有死,就会进入养老区

-XX: -XX:MaxTenuringThreshold=999 通过这个参数可以设定进入老年代的时间

image.png

  • 好处:没有内存碎片
  • 坏处:浪费一半的空间;多了一半空间永远是空 to。假设对象100%存活(极端情况)

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

复制算法的流程图:

image.png

标记清除法

标记清除法,需要两次扫描,并且清除之后会有内存碎片。

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

image.png

标记压缩

再优化!

标记–>移动–>清除

image.png

标记清除压缩

先清除5次,这样内存碎片就很多,再压缩~

image.png

再压缩1次~

image.png

总结

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

内存整齐度:复制算法 = 标记清除压缩算法 > 标记清除算法

内存利用率:标记清除压缩算法 = 标记清除算法 > 复制算法

思考一个问题:难道没有最优算法吗?

答案:没有。没有最好的算法,只有最合适的算法----->GC:粉黛收集算法

年轻代:

  • 存活率低
  • 复制算法!

老年代:

  • 区域大:存活率高(不适合 用复制算法)
  • 标记清除(当内存碎片不是太多时用标记清除) + 标记压缩混合实现

JMM

JMM:Java Memory Model Java内存模型

学习方法,先掌握总体路线、思路:

  1. 什么是JMM?

    JMM是抽象的概念,并不真实存在,它描述的是一组规则或规范,通过这组规范定义了程序中各个变量(包括实例字段,静态字段和构成数组对象的元素)的访问方式。

  2. 它是干嘛的?:参考官方,其他人的博客,对应的视频!

    作用:缓存一致性协议,用于定义数据读写的规则(遵守,找到这个规则)

    image.png

    解决共享对象可见性这个问题:volatile

    1. 它该如何学习?

    内存交互操作的8种方式:

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

    规则:

    • 不允许一个线程无原因地把数据从工作央存同步到主内存中;

    • 不允许一个线程丢弃最近assign的操作而不同步到主内存中;

    • 不允许一个变量在主内存多过”诞生“,也不允许在工作内存直接使用未初始化(load或assign)的变量;

    • 不允许一个变量在同一时刻有多个线程对其进行lock操作,仅允许一个线程Lock住并重复执行多次,多次lock需要相同次数的unlock操作,变量才会解锁。

    • 一个变量被Lock,会将清空工作内存中的此变量的值,在执行引擎使用这个变量前,需要重新执行load或assign操作初始化变量的值。

    • 不允许UnLock,一个没有lock的变量,也不允许unlock一个被其他线程Lock的对象;

    • 一个变量被执行unlock操作之前必须先把该变量同步回主内存中(执行store、write操作)

JMM如何保证多线程环境下的线程同步问题呢?

使用volatile关键字。

许一个线程无原因地把数据从工作央存同步到主内存中;

  • 不允许一个线程丢弃最近assign的操作而不同步到主内存中;

  • 不允许一个变量在主内存多过”诞生“,也不允许在工作内存直接使用未初始化(load或assign)的变量;

  • 不允许一个变量在同一时刻有多个线程对其进行lock操作,仅允许一个线程Lock住并重复执行多次,多次lock需要相同次数的unlock操作,变量才会解锁。

  • 一个变量被Lock,会将清空工作内存中的此变量的值,在执行引擎使用这个变量前,需要重新执行load或assign操作初始化变量的值。

  • 不允许UnLock,一个没有lock的变量,也不允许unlock一个被其他线程Lock的对象;

  • 一个变量被执行unlock操作之前必须先把该变量同步回主内存中(执行store、write操作)

JMM如何保证多线程环境下的线程同步问题呢?

使用volatile关键字。

JMM部分参考JMM模型是什么?

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

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

相关文章

Unity VR开发教程 OpenXR+XR Interaction Toolkit(八)手指触控 Poke Interaction

文章目录 📕教程说明📕XR Poke Interactor📕与 UI 进行触控交互⭐添加 Tracked Device Graphic Raycaster 和 XR UI Input Module 让 UI 可被交互 📕与物体进行交互⭐XR Simple Interactable⭐XR Poke Filter 往期回顾&#xff1a…

【Linux进程】进程的基本概念 {PCB结构体,进程表,Linux中的task_struct,查看进程,获取进程PID,使用fork创建子进程}

一、进程的基本概念 1.1 什么是进程? 进程是计算机中正在运行的程序的实例。它是操作系统进行资源分配和调度的基本单位。每个进程都有自己的内存空间、代码、数据和执行状态。进程可以独立运行,相互之间不会干扰。操作系统可以同时运行多个进程&#…

vue表格实现一个简单的合并单元格功能

用的是vue2ant-design-vue 但是vue3或者element-ui也是同理 先上效果 需要后端的数据将相同id的放在一起 否则也会有问题 例如: this.list [{id: 1,name: 舟山接收站,...}{id: 2,name: 舟山接收站碳中和LNG,...},{id: 2,name: 舟山接收站碳中和LNG,...} ]// th…

Redis7【⑤ Redis 发布 订阅】

Redis发布和订阅 本章了解即可,命令可以不用敲。 Redis 发布和订阅(Publish/Subscribe,简称 Pub/Sub)是一种消息传递模式,用于在 Redis 中实现消息的发布和订阅。 在 Redis 中,发布者(Publi…

maven打包所有依赖,对外提供sdk.jar

maven打包所有依赖 <properties><project.build.sourceEncoding>UTF-8</project.build.sourceEncoding><maven.compile.source>1.8</maven.compile.source><maven.compile.target>1.8</maven.compile.target></properties><…

Swin Transformer训练报错问题

1. 训练遇到报错问题 &#xff08;1&#xff09;mportError: cannot import name _pil_interp from timm.data.transforms 原因&#xff1a; timm.data.transforms里面没有_pil_interp&#xff0c;只有str_to_pil_interp、_str_to_pil_interpolation、_pil_interpolation_to_s…

rancher 节点重启无感发布

这里设置 时间 为120s &#xff0c;保证 新节点起来后&#xff0c;和 老节点并行2分钟后再剔除&#xff0c;老节点

el-select修改样式

目录 准备 修改placeholder颜色 修改右侧箭头 修改圆角边框 准备 <el-select v-model"goodsId" clearable placeholder"请选择" :popper-append-to-body"false"><el-option v-for"item in kindList" :key"item.value…

浙江宇视科技 网络视频录像机 ISC LogReport.php 远程命令执行漏洞

免责声明 文章仅供参考&#xff0c;任何个人和组织使用网络应当遵守宪法法律&#xff0c;遵守公共秩序&#xff0c;尊重社会公德&#xff0c;不得危害网络安全&#xff0c;不得利用网络从事危害国家安全、荣誉和利益&#xff0c;未经授权请勿利用文章中的技术资料对任何计算机…

Vue Router activated deactivated 路由守卫

6.12.activated deactivated activated和deactivated是路由组件所独有的两个钩子&#xff0c;用于捕获路由组件的激活状态具体使用 activated路由组件被激活时触发deactivated路由组件失活时触发 src/pages/News.vue <template><ul><li :style"{opacity}…

1.2-程序设计语言与流程图基础

一、学习目标 了解计算机程序与程序设计语言。认识算法和流程图。理解计算机程序、程序设计语言、算法与流程图之间的关系。 1、计算机程序 计算机程序是人们使用指定的程序设计语言&#xff0c;根据需要事先编写的一系列控制计算机工作的命令。2、程序设计语言 程序设计语…

如何避免死锁:方法一

需要先看前文&#xff1a;死锁的产生_御坂美琴1的博客-CSDN博客 对两个资源使用一把锁。即小朋友玩敲鼓的时候会同时拿走鼓和鼓槌。 如图&#xff1a; 可以看到“线程1执行了&#xff0c;但是线程2没有执行&#xff0c;还在被阻塞着。为什么线程1运行完毕&#xff0c;线程2还没…

解决sourcetree中推送不显示分支 - 软件篇

问题&#xff1a; 如上图所示&#xff0c;在我们使用sourcetree推送我们的代码时 推送的弹窗里不回显示我们的分支&#xff1b; 众所周知&#xff1a;在我们没有新创建分支的情况下&#xff0c;他会默认有一个master分支&#xff0c;这也是我们的主分支 在网上搜这个问题&…

61 KVM Skylark虚拟机混部-使用及最佳实践

文章目录 61 KVM Skylark虚拟机混部-使用及最佳实践61.1 使用Skylark61.1.1 启动服务61.1.2 创建虚拟机61.1.3 虚拟机运行 61.2 最佳实践61.2.1 虚拟机业务推荐61.2.2 虚拟机绑核配置 61 KVM Skylark虚拟机混部-使用及最佳实践 61.1 使用Skylark 61.1.1 启动服务 初次启动&a…

Spring MVC的工作原理

1.Spring MVC的工作原理 1.浏览器发送请求&#xff0c;DispatcherServlet拦截请求 2.DispatcherServlet将需要先调用HandlerMapping通过uri找到能够处理请求的Handler&#xff0c;然后将请求涉及到的Handler封装 3.DispatcherServlet调用HandlerAdapter适配执行Handler 4.H…

LeetCode 打卡day45-- 单词拆分和多重背包问题

一个人的朝圣 — LeetCode打卡第45天 知识总结 Leetcode 139. 单词拆分题目说明代码说明 知识总结 今天写了一道题目, 但是还挺难的, 而且是面试高频题目 还过了一遍多重背包问题. 多重背包与01背包的区别在于多重背包限制了物品的个数, 某些物品的个数可能不为1, 可以使用两…

Java缓存简介

一、缓存 1、什么是缓存&#xff1f; 缓存是硬件&#xff0c;是CPU中的组件&#xff0c;CPU存取数据的速度非常的快&#xff0c;一秒钟能够存取、处理十亿条指令和数据&#xff08;术语&#xff1a;CPU主频1G&#xff09;&#xff0c;而内存就慢很多&#xff0c;快的内存能够达…

数据库实验-图书销售管理系统数据库安全管理

一、实验二&#xff1a;图书销售管理系统数据库安全管理 三、实验目的 了解该DBMS系统对数据库管理的内容与方法&#xff0c;特别是理解数据库安全机制和作用&#xff0c;以及PostgreSQL数据库角色管理、用户管理、权限管理的基本方法&#xff0c;培养数据库管理能力。在图书…

CV什么时候能迎来ChatGPT时刻?

卷友们好&#xff0c;我是rumor。 最近看了几篇CV的工作&#xff0c;肉眼就感受到了CVer们对于大一统模型的“焦虑”。 这份焦虑让他们开始尝试统一一切&#xff0c;比如&#xff1a; 统一复杂的自动驾驶任务的优化目标[1]&#xff0c;来自今年CVPR最佳论文。统一典型的CV任务&…

3s定时循环启动弹窗,子窗体3s后自动关闭功能实现

只贴关键代码&#xff1a; 1、父窗体关键代码 private void doAt1AM(object state){//要执行的任务&#xff0c;直接button调用即可//执行功能...的任务spring_Form spr_Form new spring_Form();spr_Form.Txt "陈先生" ";到1号窗口取药";spr_Form.Show…