学习笔记4——JVM运行时数据区梳理
学习笔记系列开头惯例发布一些寻亲消息
链接:https://baobeihuijia.com/bbhj/contents/3/192489.html

类装载器classLoader:
-
将本地的字节码文件.class 加载到内存方法区中成为元数据模板(两个class对象是否为同一个类要求:完整类名包括包名一致+加载类的classloader要一致)
-
启动类加载器,用于提供JVM自身需要的类(除了启动类加载器,其他都继承自classloader)
-
扩展类加载器:从用户指定目录中加载类
-
应用程序类加载器:加载环境变量/系统属性指定路径下的类库,是程序中默认的类加载器
-
用户自定义类加载器
-
双亲委派机制:
- 按需加载,需要用到该类的时候才会加载到内存中生成class对象
- 向上委托,父类加载失败则由子加载器处理
- 优点:
- 避免类重复加载
- 防止核心api被随意更改【沙箱安全】:自定义string类,在加载的自定义string类的时候会率先使用引导类加载器加载jdk自带的string.class文件,可以保证对java核心源代码的保护


运行时数据区:
-
JAVA内存布局规定了java运行过程中内存申请,分配和管理的策略:
-
每个线程独立拥有程序计数器、栈、本地方法栈
-
线程共享,随虚拟机存亡的:方法区、堆
-
程序计数器
-
(由于cpu一直在线程中切换,利用程序计数器可以记住切回来后继续执行的位置【cpu时间片:cpu分给各个线程的时间段】)
-
pc寄存器用来存储指向下一条指令的地址/如果该线程执行的是native方法,则是未指定值
-
通过pc来控制程序的分支、循环、跳转等
-
字节码解释器就是通过pc来找到下一条即将要执行的字节码指令
-
是jvm中唯一一个没有规定任何outofmemoryerror情况的
-
虚拟机栈(栈帧就类似于寄存器之间的倒换)
- java的指令都是基于栈来设计的,因为不同的平台cpu架构不同,所以不能设计基于寄存器的
- 随着方法的执行,java栈的操作就是对栈帧的入栈还有出栈,不存在垃圾回收问题(之前的基于寄存器的方法执行是通过寄存器来转移操作数据)
- 栈可能出现的异常
- 线程请求分配的栈容量超过java的栈最大容量,就抛出stackoverflowerror异常
- 如果是没有内存来创建或者满足栈要求,就抛出outofmemoryerror异常
- 每个线程都有自己的栈,栈中数据是以栈帧格式存在的,执行引擎运行所有的字节码指令只针对当前栈帧进行,也就是说一个时间点只会有一个活动的栈帧,如果该方法调用了别的方法,那么别的方法的栈帧就会被创建并放到栈顶端,成为当前栈帧
- 栈帧中包括:
- 局部变量表
- 局部变量表所需的大小在编译的时候就写在了字节码文件中,所以大小是固定的
- 以slot为基本存储单位
- 当一个方法被执行引擎调用的时候,该方法的方法参数和内部定义的局部变量都会按照执行顺序被复制到局部变量表中的slot上
- 局部变量表必须进行人为的初始化,没有系统自带的准备阶段初始为0,没有赋值就不能使用
- 操作数栈
- 保存计算过程的中间结果,同时是计算过程中变量的临时存储空间
- 并非使用索引来进行数据访问,而是通过数据的出栈和入栈来完成一次访问
- 栈顶缓存技术:将频繁的栈顶读写缓存到物理cpu中,降低对内存的读写
- 动态链接(指向运行时常量池的方法引用,将符号转化为调用方法的直接引用)
- 静态链接(早期绑定):在编译期可知,且运行期不变,用静态链接直接替换
- 动态链接(晚期绑定):编译期无法确定,要根据程序运行时的实际类型才能确定【比如我们是通过一个变量值>3来判断执行哪个方法,像这样就无法直接替换,就需要在运行时进行动态的链接/支持多态】
- 虚方法表:每次动态分派的过程都要在类的方法元数据中找到合适的目标,因此在类的方法区建立虚方法表使用索引来代替查找
- 方法返回地址
- 存放调用该方法的pc寄存器的值,即调用该方法的下一条指令的地址
- 若是异常退出,则返回地址是要通过异常表来确定
- 局部变量表

Java方法内的局部变量是否线程安全问题_在方法中会产生线程安全问题吗对吗-CSDN博客
本地方法栈
-
调用本地的一些基于C编写的程序时,采用本地方法栈来管理本地方法的调用
-
当某个线程调用一个本地方法时,它就进入了一个全新的并且不再受虚拟机限制的世界。它和虚拟机拥有同样的权限。
堆
-
是JVM中分配内存最大的一块区域,如果内存大小超过-Xmx指定的最大内存就会抛出outofmemeryerror
-
为什么xms和xmx要设置成相同的值?【精选】jvm调优技巧 - 内存抖动 、Xms和Xmx参数为什么要设置相同的值_xmx和xms为什么要一样-CSDN博客
xms是发现空余堆内存大于阈值,jvm减小直到xms最小
xmx是发现空余堆内存小于阈值,jvm增大直到xmx最大
1、首先,如果-Xms起初值设置的比较小,那么就频繁触发GC操作。当GC操作无法释放更多内存时,会进行内存的扩充。
2、内存扩充的时候,会出现内存抖动的情况
【就比如我上街看到一个很喜欢的商品,想要买下这个商品,但是我身上的钱不够了, 于是我向你借钱,你同意了,然后你掏出钱包, 把钱拿出来,然后再交给我,你拿钱给我的这整个过程也是需要时间的。所以我为了省下这个拿钱的时间,我在一开始出门的时候就直接带上足够的钱,这样就可以省下借钱的时间了】
-
-
为对象分配内存TLAB
- 为避免多个线程操作同一堆区的对象地址,使用TLAB机制,如果失败那就使用加锁机制确保数据操作的原子性
-
对象不一定全部分配在堆上,采用逃逸分析时,即对象只在方法体内使用时,也可以分配到栈中



方法区
- 实际物理内存空间和堆一样可以不连续的,如果方法区定义了太多的类,那么方法区也会outpfmemoryerror
- 在这个类加载阶段包括两部分,一是对静态变量的加载(分为static和final static),二是对类的加载
- 内部结构
- 类型信息:全名(包名.类名),直接父类的完整有效名,修饰符,直接接口
- 域信息
- 方法信息:方法名,方法返回类型,参数,修饰符,字节码,操作数栈,局部变量表以及大小,异常表
- 方法区是运行时常量池、字节码文件内部包含常量池

常量池(字节码)和运行时常量池(方法区)
-
一个java源文件中的类、接口,编译后产生一个字节码文件。而Java中的字节码需要数据支持,通常这种数据会很大以至于不能直接存到字节码里,换另一种方式,可以存到常量池,这个字节码包含了指向常量池的引用。
-
这部分内容在类加载后存放到方法区的运行时常量池中,其中每个已加载的类都会维护一个常量池,通过索引访问
- 编译期就明确数值字面量
- 运行期才能获得方法或者字段引用,此时就不再是常量池中的符号地址了,而是真实地址
大概梳理流程:
【创建轮子,车架】我将我的java文件打包生成字节码文件,当我点击运行的时候,启动类会被主动加载,jvm的类加载器就会
- 加载类中的静态变量到方法区,直接分配内存(可能分配到永久代/堆)
- 加载字节码中的类信息到方法区(按需加载,需要用到该类的时候才会加载到内存),包括类名,域名,方法名,并且将类的常量池放到方法区的运行时常量池中(根据这个信息才能将类完整的刻画出来),将符号引用变为直接的内存地址
【实例化四个轮子,车架】jvm开启线程,主动对启动类进行类的初始化:先进行类初始化,即将方法区/堆区的静态变量进行初始化,执行静态代码块,然后是对象初始化,new的对象放到jvm的堆中,执行赋值语句,普通代码块,最后是构造函数代码。
【组装】jvm在栈中开启一个栈帧记录线程,在运行时加载该方法的局部变量表,利用操作栈对数据进行循环,遍历运算,如果在执行过程中遇到了对象引用,那就去方法区的运行时常量池将符号转化为直接引用,执行完毕后,堆中的对象被清除。

面试题


当在多次minor GC后仍然存活的满足一定存活代数的对象,或者是由于太大无法在新生代中分配的对象

java8之前,两种模式
- 所有的类信息(运行时常量池)和静态变量,字符串常量都放在永久代上
- 只剩类信息(运行时常量池)在永久代 / 静态变量,字符串常量放在堆中
java8之后
- jvm没有永久代的概念,类信息(运行时常量池)放在本地内存上,叫元空间
为什么有这个变动呢?
- 因为随着类加载变多,我们无法定义一个合适的永久代空间,因此放到本地的话,元空间的大小只受限于本地的内存大小
- 原始字符串常量放在永久代中,只有full GC(老年代或者永久代不足)的时候才会被清理,回收效率不高,所以新的改进是放到堆中,跟随对象及时回收内存
行时常量池)放在本地内存上,叫元空间
为什么有这个变动呢?
- 因为随着类加载变多,我们无法定义一个合适的永久代空间,因此放到本地的话,元空间的大小只受限于本地的内存大小
- 原始字符串常量放在永久代中,只有full GC(老年代或者永久代不足)的时候才会被清理,回收效率不高,所以新的改进是放到堆中,跟随对象及时回收内存
相关文章:
学习笔记4——JVM运行时数据区梳理
学习笔记系列开头惯例发布一些寻亲消息 链接:https://baobeihuijia.com/bbhj/contents/3/192489.html 类装载器classLoader: 将本地的字节码文件.class 加载到内存方法区中成为元数据模板(两个class对象是否为同一个类要求:完整…...
Splunk 创建特色 dashboard 报表
1: 背景: 对原有的dashboard 进行增加点东西,特别是文字部分: 比如: 增加:“this is a guidline for how to use performance". 这段话,就不能写在title, 那样,这段文字,会出现在dashboard 的PDF 文件的分割线的上面,不符合要求。 2: 解决问题: 正确的做法是…...
如何在校园跑腿系统小程序中构建稳健的订单处理与分配系统?
1. 数据库设计 首先,设计订单数据结构。使用数据库(例如MySQL、MongoDB等),创建订单表以存储订单相关信息,包括订单ID、用户信息、交付地址、订单状态等。 CREATE TABLE orders (order_id INT AUTO_INCREMENT PRIMAR…...
数据结构与算法—双链表
前言 前面有很详细的讲过线性表(顺序表和链表),当时讲的链表以单链表为主,但在实际应用中双链表有很多应用场景,例如大家熟知的LinkedList。 双链表与单链表区别 单链表和双链表都是线性表的链式实现,它们的主要区别在于节点结构…...
linux继续循环案例测试ping网络,目录下的文件权限循环输出
第一:查看本机ip #ip addr 通过脚本访问本机ip1-100,是否可以ping通,并显示结果,上图 知识点 ping -c 数字1 -w 数字1,向目的ip发送1个数据包,等待1秒,无回复中止 &>/dev/null 知…...
关于SSP3D复现
关于SSP3D复现的问题 准备工作 下载Xshell和XFTP:家校免费版下载链接连接服务器(可能需要与服务器处在相同网络下)GitHub上下载源码:SSP3D 左上角新建会话,输入名称和主机 点击左侧菜单“用户身份验证”,…...
在直播系统中使用RTSP协议传递视频
目录 概述 1、环境准备 2、拉流URL地址 3、导播软件取流 (1)OBS中拉取RTSP流 (2)芯象中拉取RTSP流 (3)vMix中拉取RTSP流 写在最后 概述 提到RTSP协议,很容易想到RTMP协议,它…...
Notion汉化
Notion真无语,汉化版都没有。真的无力吐槽。 2023.11.7汉化经历 教程链接:github Reamd7/notion-zh_CN at 2.4.20-handmade (github.com) 网页版: 油猴下载插件。 Notion中文汉化 浏览器插件下载 windows: github realse 这…...
echarts有背景的柱状图,鼠标滑过提示信息都是展示背景柱状图的值
// 上一篇文章介绍了如何实现有背景的柱状图,现在又遇到一个问题,鼠标滑过柱子,提示信息是背景柱子的值,解决方案,自定义tooltip的formatter,上代码tooltip: {//鼠标悬浮提示数据formatter: function (para…...
华为防火墙基本原理工作方法总结
防火墙只会对tcp首包syn建立会话表,其它丢掉,如synack,ack udp直接建立会话表 icmp只对首包请求包建立会话表,其它包,如应答的不会建立直接丢掉 防火墙状态查看: rule name trust_untrust source-zone tru…...
Spring Cloud之多级缓存
目录 传统缓存 多级缓存 JVM进程缓存 Caffeine 缓存驱逐策略 实现进程缓存 常用Lua语法 数据类型 变量声明 循环使用 定义函数 条件控制 安装OpenResty 实现Nginx业务逻辑编写 请求参数解析 实现lua访问tomcat JSON的序列化和反序列化 Tomcat的集群负载均衡 …...
融云荣登「2023 年度 PaaS 企业排行榜」
11 月 2 日,中国科学院旗下《互联网周刊》颁布“2023 年度 PaaS 企业排行榜”,融云荣登榜单。关注【融云全球互联网通信云】了解更多 根据中国信息通信研究院《云计算白皮书 2023》:2022 年,PaaS 增长强势,总收入 342 …...
YOLOv8轻量化模型:模型轻量化设计 | 轻量级可重参化EfficientRep| 来自YOLOv6思想
💡💡💡本文解决什么问题:在几乎不保证精度下降的前提下,轻量级模型创新设计 EfficientRep 在关键点检测任务中 | GFLOPs从9.6降低至8.5, mAP50从0.921下降至0.912,mAP50-95从0.697提升至0.779 YOLO轻量化模型专栏:http://t.csdnimg.cn/AeaEF 1.YOLOv6介绍 论文…...
【JavaSE】基础笔记 - 类和对象(下)
目录 1、this引用 1.1、为什么要有this引用 1.2、什么是this引用 1.3、 this引用的特性 2、 对象的构造及初始化 2.1、 如何初始化对象 2.2、构造方法 2.2.1、概念 2.2.2、特性 2.3、默认初始化 2.4、就地初始化 上篇:【JavaSE】基础笔记 - 类和对象&#…...
浅析刚入门Python初学者的注意事项
文章目录 一、注意你的Python版本1.print()函数2.raw_input()与input()3.比较符号,使用!替换<>4.repr函数5.exec()函数 二、新手常遇到的问题1、如何写多行程序?2、如何执行.py文件?3、and,or,not4、True和False…...
2023NOIP A层联测26 总结
T1 求 ∑ i 1 n ∑ j i n ( ⨁ k i j a k ) 2 \sum\limits_{i1}^n\sum\limits_{ji}^n\left(\bigoplus\limits_{ki}^{j}a_k\right)^2 i1∑nji∑n(ki⨁jak)2, n , a i ≤ 2 1 0 5 n,a_i\le2\times10^5 n,ai≤2105。先转成前缀和,然后就没思…...
响应式编程-Project Reactor Mono 介绍
响应式编程-Project Reactor Mono 介绍 本文以Mono的角度来介绍Reactor编程,Flux的使用同理。 初体验 Web应用 controller 方法在Spring webmvc 和 Spring webFlux下Controller方法实现示例如下: Spring webmvc: GetMapping("/test1") …...
R语言实操记录——导出高清图片(矢量图)
R语言 R语言实操记录——导出高清图片(矢量图) 文章目录 R语言一、起因(闲聊,可跳过)二、如何在R中导出高清图片(矢量图)2.1、保存为EPS图片格式后转AI编辑2.2、保存为PDF格式(推荐…...
Apache Doris 开源最顶级基于MPP架构的高性能实时分析数据库
背景介绍 Apache Doris是一个基于MPP架构的易于使用,高性能和实时的分析数据库,以其极高的速度和易用性而闻名。海量数据下返回查询结果仅需亚秒级响应时间,不仅可以支持高并发点查询场景,还可以支持高通量复杂分析场景。 这些都…...
webgoat-Request Forgeries 请求伪造
(A8:2013) Request Forgeries Cross-Site Request Forgeries 跨站请求伪造,又称一键攻击或会话骑乘,简称CSRF (有时发音为 sea-surf)或 XSRF,是一种恶意利用网站,其中传输未经授权的命令 来自网站信任的用…...
idea大量爆红问题解决
问题描述 在学习和工作中,idea是程序员不可缺少的一个工具,但是突然在有些时候就会出现大量爆红的问题,发现无法跳转,无论是关机重启或者是替换root都无法解决 就是如上所展示的问题,但是程序依然可以启动。 问题解决…...
汽车生产虚拟实训中的技能提升与生产优化
在制造业蓬勃发展的大背景下,虚拟教学实训宛如一颗璀璨的新星,正发挥着不可或缺且日益凸显的关键作用,源源不断地为企业的稳健前行与创新发展注入磅礴强大的动力。就以汽车制造企业这一极具代表性的行业主体为例,汽车生产线上各类…...
深入解析C++中的extern关键字:跨文件共享变量与函数的终极指南
🚀 C extern 关键字深度解析:跨文件编程的终极指南 📅 更新时间:2025年6月5日 🏷️ 标签:C | extern关键字 | 多文件编程 | 链接与声明 | 现代C 文章目录 前言🔥一、extern 是什么?&…...
JVM暂停(Stop-The-World,STW)的原因分类及对应排查方案
JVM暂停(Stop-The-World,STW)的完整原因分类及对应排查方案,结合JVM运行机制和常见故障场景整理而成: 一、GC相关暂停 1. 安全点(Safepoint)阻塞 现象:JVM暂停但无GC日志,日志显示No GCs detected。原因:JVM等待所有线程进入安全点(如…...
selenium学习实战【Python爬虫】
selenium学习实战【Python爬虫】 文章目录 selenium学习实战【Python爬虫】一、声明二、学习目标三、安装依赖3.1 安装selenium库3.2 安装浏览器驱动3.2.1 查看Edge版本3.2.2 驱动安装 四、代码讲解4.1 配置浏览器4.2 加载更多4.3 寻找内容4.4 完整代码 五、报告文件爬取5.1 提…...
MySQL用户和授权
开放MySQL白名单 可以通过iptables-save命令确认对应客户端ip是否可以访问MySQL服务: test: # iptables-save | grep 3306 -A mp_srv_whitelist -s 172.16.14.102/32 -p tcp -m tcp --dport 3306 -j ACCEPT -A mp_srv_whitelist -s 172.16.4.16/32 -p tcp -m tcp -…...
如何在网页里填写 PDF 表格?
有时候,你可能希望用户能在你的网站上填写 PDF 表单。然而,这件事并不简单,因为 PDF 并不是一种原生的网页格式。虽然浏览器可以显示 PDF 文件,但原生并不支持编辑或填写它们。更糟的是,如果你想收集表单数据ÿ…...
Java + Spring Boot + Mybatis 实现批量插入
在 Java 中使用 Spring Boot 和 MyBatis 实现批量插入可以通过以下步骤完成。这里提供两种常用方法:使用 MyBatis 的 <foreach> 标签和批处理模式(ExecutorType.BATCH)。 方法一:使用 XML 的 <foreach> 标签ÿ…...
基于TurtleBot3在Gazebo地图实现机器人远程控制
1. TurtleBot3环境配置 # 下载TurtleBot3核心包 mkdir -p ~/catkin_ws/src cd ~/catkin_ws/src git clone -b noetic-devel https://github.com/ROBOTIS-GIT/turtlebot3.git git clone -b noetic https://github.com/ROBOTIS-GIT/turtlebot3_msgs.git git clone -b noetic-dev…...
JVM 内存结构 详解
内存结构 运行时数据区: Java虚拟机在运行Java程序过程中管理的内存区域。 程序计数器: 线程私有,程序控制流的指示器,分支、循环、跳转、异常处理、线程恢复等基础功能都依赖这个计数器完成。 每个线程都有一个程序计数…...
