当前位置: 首页 > news >正文

JVM图文入门

往期推荐

【已解决】redisCache注解失效,没写cacheConfig_com.howbuy.cachemanagement.client.redisclient#incr-CSDN博客

【已解决】OSS配置问题_keyuewenhua.oss-cn-beijing.aliyuncs-CSDN博客

【排坑】云服务器docker部署前后端分离项目+域名解析+OSS-CSDN博客

微服务概念入门:Nacos、OpenFeign、Sentinel、GateWay、Seata-CSDN博客

字符串常量池-CSDN博客

目录

1. JVM8结构图

2. Java性能低的主要原因

3. 字节码文件

3.1 字节码文件的组成

4. JVM架构

4.1 类加载器ClassLoader

4.2 运行时数据区

程序计数器

Java虚拟机栈(方法栈)

本地方法栈 

4.3 执行引擎

5. 双亲委派

5.1 破坏双亲委派

Tomcat破坏

JDBC破坏 


1. JVM8结构图

2. Java性能低的主要原因

Java语言如果不做任何的优化,性能其实是不如C和C++语言的。主要原因是:

在程序运行过程中,Java虚拟机需要将字节码指令实时地解释成计算机能识别的机器码,这个过程在运行时可能会反复执行,所以效率较低。

C和C++语言在执行过程中,只需将源代码编译成可执行文件,就包含了计算机能识别的机器码,无需在运行过程中再实时地解释,所以性能较高。

 Java为什么要选择一条执行效率比较低的方式呢?主要是为了实现跨平台的特性。Java的字节码指令,如果希望在不同平台(操作系统+硬件架构),比如在windows或者linux上运行。可以使用同一份字节码指令,交给windows和linux上的Java虚拟机进行解释,这样就可以获得不同平台上的机器码了。这样就实现了Write Once,Run Anywhere 编写一次,到处运行。

3. 字节码文件

我们java中说的字节码文件即 java代码编译后的.class文件,class文件可以跨平台运行在不同操作系统的JVM上。

3.1 字节码文件的组成

字节码文件总共可以分为以下几个部分:

  • 基础信息:魔数、字节码文件对应的Java版本号、访问标识(public final等等)、父类和接口信息

  • 常量池保存了字符串常量、类或接口名、字段名,主要在字节码指令中使用

  • 字段: 当前类或接口声明的字段信息

  • 方法: 当前类或接口声明的方法信息,核心内容为方法的字节码指令

  • 属性: 类的属性,比如源码的文件名、内部类的列表等

4. JVM架构

根据上面的JVM图,JVM大致可分为三块: 类加载器ClassLoader、运行时数据区 、执行引擎

4.1 类加载器ClassLoader

类加载器会通过二进制流的方式获取到字节码文件并交给Java虚拟机,虚拟机会在方法区和堆上生成对应的对象保存字节码信息。

根加载器(启动类加载器):

 默认加载Java安装目录/jre/lib下的类文件,比如rt.jar,tools.jar,resources.jar等。

扩展类加载器:

 默认加载Java安装目录/jre/lib/ext下的类文件

应用程序类加载器(系统类加载器):

 默认加载的是项目中的类以及通过maven引入的第三方jar包中的类。

用户自定义类加载器

输出为null是因为根加载器的具体实现是由C或C++编写,不在java范围内。 

4.2 运行时数据区

运行时数据可以划分为以下5块

程序计数器

每个线程都有一个私有的程序计数器,也就是一个指针,指向方法区中的方法字节码(用来存储指向指令的地址)。解释器会在工作的时候改变这个计数器的值来选取下一条需要执行的字节码指令。如果线程执行的是非本地方法,则程序计数器中保存的是当前需要执行的指令地址;如果线程执行的是本地方法,则程序计数器中的值是 undefined。

Java虚拟机栈(方法栈)

栈中没有垃圾回收的,线程结束后内存会自动释放。栈主管程序运行、生命周期、线程同步。

Java 虚拟机栈中是一个个栈帧,每个栈帧对应一个被调用的方法,当线程执行一个方法时,会创建一个对应的栈帧,并将栈帧压入栈中。当方法执行完毕后,将栈帧从栈中弹出。

栈帧及组成

  • 局部变量表,局部变量表的作用是在运行过程中存放所有的局部变量

  • 操作数栈,操作数栈是栈帧中虚拟机在执行指令过程中用来存放临时数据的一块区域

  • 帧数据,帧数据主要包含动态链接、方法出口、异常表的引用

stack1的方法结束后要弹出栈,此时需要通过stack1返回下面的stack2的方法。 

本地方法栈 

Java虚拟机栈存储了Java方法调用时的栈帧,而本地方法栈存储的是native本地方法的栈帧

public class Test {    public static void main(String[] args) {        Student s1 = new Student();        s1.name = "张三";       s1.age = 18;       s1.id = 1;s1.printTotalScore();        s1.printAverageScore();        Student s2 = new Student();       s2.name = "李四";        s2.age = 19;        s2.id= 2;        s2.printTotalScore();        s2.printAverageScore();    }
}

这段代码中通过new关键字创建了两个Student类的对象,这两个对象会被存放在堆上。在栈上通过s1s2两个局部变量保存堆上两个对象的地址,从而实现了引用关系的建立。

以前的Java 中“几乎”所有的对象都会在堆中分配,但随着JIT编译器的发展和逃逸技术的逐渐成熟,所有的对象都分配到堆上渐渐变得不那么“绝对”了。从 JDK 7 开始,Java 虚拟机已经默认开启逃逸分析了,意味着如果某些方法中的对象引用没有被返回或者未被外面使用(也就是未逃逸出去),那么对象可以直接在栈上分配内存。垃圾指JVM中没有任何引用指向它的对象

逃逸分析

逃逸分析是一种编译器优化技术,用于判断对象的作用域和生命周期。如果编译器确定一个对象不会逃逸出方法或线程的范围,它可以选择在栈上分配这个对象,而不是在堆上。这样做可以减少垃圾回收的压力,并提高性能。

一个JVM实例只有一个堆内存,堆内存大小可以调节,类加载器读取类文件后要把类、方法、常变量放到堆内存中,保存所有引用类型的真实信息,堆内存在逻辑上分为三部分:

  • 新生代:伊甸区、幸存0区 from、幸存1区 to
  • 老年代
  • 永久代

4.3 执行引擎

5. 双亲委派

应用程序类加载器(又叫系统类加载器)收到类的加载请求先检查自己是否加载过该类,如果没有,将请求向上委托给自己的父类加载器(extensionLoader),如果父类加载器也没有加载过该类,该父类加载器继续向上委托给自己的父类加载器(bootstrapLoader,又叫根加载器、启动类加载器)若启动类加载器也没有加载过该类,则会根据要加载的类的全限定名尝试加载该类,若加载成功,则返回引用,若加载失败,则抛出异常,并反向委托给扩展类加载器,若仍加载失败,则继续抛出异常,并反向委托给应用程序类加载器,若仍加载失败,则报异常ClassNotFound。

安全性和沙箱机制

由于java核心库和扩展库由根加载器加载,这些库中的类有更高的安全级别,而应用程序类由应用程序类加载器加载,安全级别低,双亲向上委派可以防止核心API被篡改,提高了程序安全性。

什么是沙箱?

java安全模型的核心就是java沙箱,沙箱是一个限制程序运行的环境,沙箱机制就是把java代码限定在jvm的特定运行范围内,严格限制代码对本地系统资源的访问(CPU、内存、文件系统、网络等),通过这样来保证代码的有效隔离,防止对本地系统造成破坏。

避免类重复加载

由于父类加载器加载类时会优先尝试加载,若类已经被加载过,就不会再次加载,避免了类重复加载。 

5.1 破坏双亲委派

打破双亲委派机制历史上有三种方式,但本质上只有第一种算是真正的打破了双亲委派机制:

  • 自定义类加载器并且重写loadClass方法。Tomcat通过这种方式实现应用之间类隔离。

  • 线程上下文类加载器。利用上下文类加载器加载类,比如JDBC和JNDI等。

  • Osgi框架的类加载器。历史上Osgi框架实现了一套新的类加载器机制,允许同级之间委托进行类的加载,目前很少使用。

Tomcat破坏

JDBC破坏 

JDBC中使用了DriverManager来管理项目中引入的不同数据库的驱动,比如mysql驱动、oracle驱动。DriverManager类位于rt.jar包中,由启动类加载器加载。依赖中的mysql驱动对应的类,由应用程序类加载器来加载。DriverManager属于rt.jar是启动类加载器加载的。而用户jar包中的驱动需要由应用类加载器加载,这就违反了双亲委派机制存疑

JDBC案例中真的打破了双亲委派机制吗?

最早这个论点提出是在周志明《深入理解Java虚拟机》中,他认为打破了双亲委派机制,这种由启动类加载器加载的类,委派应用程序类加载器去加载类的方式,所以打破了双亲委派机制。

但是如果我们分别从DriverManager以及驱动类的加载流程上分析,JDBC只是在DriverManager加载完之后,通过初始化阶段触发了驱动类的加载,类的加载依然遵循双亲委派机制。

所以我认为这里没有打破双亲委派机制,只是用一种巧妙的方法让启动类加载器加载的类,去引发的其他类的加载。

相关文章:

JVM图文入门

往期推荐 【已解决】redisCache注解失效,没写cacheConfig_com.howbuy.cachemanagement.client.redisclient#incr-CSDN博客 【已解决】OSS配置问题_keyuewenhua.oss-cn-beijing.aliyuncs-CSDN博客 【排坑】云服务器docker部署前后端分离项目域名解析OSS-CSDN博客 微服…...

cursor 开发java项目教程简单上手

1.官网下载 Cursor - The AI Code Editor 下载完后注册账号,可以使用无限邮的方式 注册完之后 设置中文 可以选择设置为中文 Ctrl Shift X 进入设置页面输入chinese 然后重启 更改jdk跟maven仓库设置 ctrlshiftp 打开输入框后输入json,把下面代码…...

优化fm.jiecao.jcvideoplayer_lib中视频横竖屏自动适配原视频方案

fm.jiecao:jiecaovideoplayer:x.x.x 优化fm.jiecao.jcvideoplayer_lib中视频横竖屏自动适配原视频方案: 仅优化关键代码部分,源码: public void startWindowFullscreen() {Log.i(TAG, "startWindowFullscreen " " [" …...

aws(学习笔记第二十七课) 使用aws API Gateway+lambda体验REST API

aws(学习笔记第二十七课) 使用aws API Gatewaylambda体验REST API 学习内容: 使用aws API Gatewaylambda 1. 使用aws API Gatewaylambda 作成概要 使用api gateway定义REST API,之后再接收到了http request之后,redirect到lambda进行执行。…...

物联网的三层架构:感知层、网络层与应用层

物联网(Internet of Things, IoT)作为现代科技的重要组成部分,正在深刻改变我们的生活和工作方式。它将物理世界与数字世界无缝连接,通过智能设备、传感器和网络技术,实现数据的采集、传输和应用。物联网的架构通常分为…...

常用抓包工具tcpdump、Fiddler、Charles、Wireshark 和 Sniffmaster 下载地址

抓包大师官网下载地址 Sniff Master Download - Free TCP and HTTPS Proxy Sniffing Tool, Supports IOS Sniffing Fiddler classic官网下载地址 Download Fiddler Web Debugging Tool for Free by Telerik Fiddler Everywhere官网下载地址 The Ultimate Web Debugging Tool …...

π0开源了且推出自回归版π0-FAST——打造机器人动作专用的高效Tokenizer:比扩散π0的训练速度快5倍但效果相当

前言 过去的半个多月 deepseek火爆全球,我对其的解读也成了整整一个系列 详见《火爆全球的DeepSeek系列模型》,涉及对GRPO、MLA、V3、R1的详尽细致深入的解读 某种意义来讲,deepseek 相当于把大模型的热度 又直接拉起来了——相当于给大模…...

js-对象-JSON

JavaScript自定义对象 JSON 概念: JavaScript Object Notation,JavaScript对象标记法. JSON 是通过JavaScript 对象标记法书写的文本。 由于其语法简单,层次结构鲜明,现多用于作为数据载体,在网络中进行数据传输. json中属性名(k…...

Houdini subuv制作输出阵列图

在游戏开发中经常需要用到sheet阵列图,并用其制作翻页动画。通过Houdini强大的节点组合可以配合输出subuv阵列图供游戏引擎使用。 本文出处:https://zhuanlan.zhihu.com/p/391796978 博主参考学习并写该文。 1.在obj分类下创建font节点以进行测试&#…...

虚幻基础17:动画蓝图

能帮到你的话,就给个赞吧 😘 文章目录 animation blueprint图表(Graph): 编辑动画逻辑。变量(Variables): 管理动画参数。函数(Functions): 自定义…...

路由器及工作原理与常用路由配置命令详解

一、引言 在当今数字化时代,网络已经成为人们生活和工作中不可或缺的一部分。无论是家庭网络中的多台设备同时上网,还是企业网络中各个部门之间的数据传输和资源共享,都离不开网络设备的支持。路由器作为一种关键的网络设备,在网…...

Windows编程:下载与安装 Visual Studio 2010

本节前言 在写作本节的时候,本来呢,我正在写的专栏,是 MFC 专栏。而 VS2010 和 VS2019,正是 MFC 学习与开发中,可以使用的两款软件。然而呢,如果你去学习 Windows API 知识的话,那么&#xff0…...

R语言 文本分析 天龙八部

起因, 目的: 前面有人对 “倚天屠龙记” 进行分析,我这里只是进行模仿而已。 完整的文件, 已经绑定了,反正读者可以找一下。 案例背景 小说《天龙八部》是金庸先生所著的武侠小说,也是“射雕三部曲”的前传。全书共50章,字数超过一百万字。故事发生在北宋末年,以大理…...

深度学习 Pytorch 建模可视化工具TensorBoard的安装与使用

50 TensorBoard的安装和使用 在深度学习建模过程中,为了能够快速绘制模型基本结构、观察模型评估指标伴随训练过程的动态变化情况,当然也为了能够观察图像数据,我们可以使用TensorBoard工具来进行Pytorch深度学习模型的可视化展示。 Tensor…...

【免费】2007-2019年各省科技支出占一般公共预算支出的比重数据

2007-2019年各省科技支出占一般公共预算支出的比重数据 1、时间:2007-2019年 2、来源:国家统计局、统计年鉴 3、指标:行政区划代码、地区名称、年份、科技支出占一般公共预算支出的比重 4、范围:31省 5、指标解释&#xff1a…...

19爬虫:使用playwright登录超级鹰

本次案例一共解决了如下两个问题: (1)如何使用playwright截图,特别是验证码图片 (2)在playwright中如何判断一个元素可见 1.截图 我们首先解决第一个问题,截图。如果前期接触过selenium的小伙…...

[转]Java面试近一个月的面试总结

本文是在学习中的总结,欢迎转载但请注明出处:http://blog.csdn.net/pistolove/article/details/46753275 前言 打算换个工作,近一个月面试了不少的公司,下面将一些面试经验和思考分享给大家。另外校招也快要开始了,为…...

Spring Boot中使用MockMvc测试PATCH请求控制器

在Spring Boot项目中,对控制器进行单元测试是确保代码质量和功能正确性的重要环节。本文将通过一个具体的例子,展示如何使用Spring的MockMvc框架来测试处理PATCH请求的控制器。 示例项目结构 假设我们有一个简单的Spring Boot项目,其中包含一…...

html转PDF文件最完美的方案(wkhtmltopdf)

目录 需求 一、方案调研 二、wkhtmltopdf使用 如何使用 文档简要说明 三、后端服务 四、前端服务 往期回顾 需求 最近在做报表类的统计项目,其中有很多指标需要汇总,网页内容有大量的echart图表,做成一个网页去浏览,同时…...

ip地址是手机号地址还是手机地址

在数字化生活的浪潮中,IP地址、手机号和手机地址这三个概念如影随形,它们各自承载着网络世界的独特功能,却又因名称和功能的相似性而时常被混淆。尤其是“IP地址”这一术语,经常被错误地与手机号地址或手机地址划上等号。本文旨在…...

RocketMQ延迟消息机制

两种延迟消息 RocketMQ中提供了两种延迟消息机制 指定固定的延迟级别 通过在Message中设定一个MessageDelayLevel参数,对应18个预设的延迟级别指定时间点的延迟级别 通过在Message中设定一个DeliverTimeMS指定一个Long类型表示的具体时间点。到了时间点后&#xf…...

学习STC51单片机32(芯片为STC89C52RCRC)OLED显示屏2

每日一言 今天的每一份坚持,都是在为未来积攒底气。 案例:OLED显示一个A 这边观察到一个点,怎么雪花了就是都是乱七八糟的占满了屏幕。。 解释 : 如果代码里信号切换太快(比如 SDA 刚变,SCL 立刻变&#…...

企业如何增强终端安全?

在数字化转型加速的今天,企业的业务运行越来越依赖于终端设备。从员工的笔记本电脑、智能手机,到工厂里的物联网设备、智能传感器,这些终端构成了企业与外部世界连接的 “神经末梢”。然而,随着远程办公的常态化和设备接入的爆炸式…...

Pinocchio 库详解及其在足式机器人上的应用

Pinocchio 库详解及其在足式机器人上的应用 Pinocchio (Pinocchio is not only a nose) 是一个开源的 C 库,专门用于快速计算机器人模型的正向运动学、逆向运动学、雅可比矩阵、动力学和动力学导数。它主要关注效率和准确性,并提供了一个通用的框架&…...

Linux C语言网络编程详细入门教程:如何一步步实现TCP服务端与客户端通信

文章目录 Linux C语言网络编程详细入门教程:如何一步步实现TCP服务端与客户端通信前言一、网络通信基础概念二、服务端与客户端的完整流程图解三、每一步的详细讲解和代码示例1. 创建Socket(服务端和客户端都要)2. 绑定本地地址和端口&#x…...

面试高频问题

文章目录 🚀 消息队列核心技术揭秘:从入门到秒杀面试官1️⃣ Kafka为何能"吞云吐雾"?性能背后的秘密1.1 顺序写入与零拷贝:性能的双引擎1.2 分区并行:数据的"八车道高速公路"1.3 页缓存与批量处理…...

PH热榜 | 2025-06-08

1. Thiings 标语:一套超过1900个免费AI生成的3D图标集合 介绍:Thiings是一个不断扩展的免费AI生成3D图标库,目前已有超过1900个图标。你可以按照主题浏览,生成自己的图标,或者下载整个图标集。所有图标都可以在个人或…...

rm视觉学习1-自瞄部分

首先先感谢中南大学的开源,提供了很全面的思路,减少了很多基础性的开发研究 我看的阅读的是中南大学FYT战队开源视觉代码 链接:https://github.com/CSU-FYT-Vision/FYT2024_vision.git 1.框架: 代码框架结构:readme有…...

用 Rust 重写 Linux 内核模块实战:迈向安全内核的新篇章

用 Rust 重写 Linux 内核模块实战:迈向安全内核的新篇章 ​​摘要:​​ 操作系统内核的安全性、稳定性至关重要。传统 Linux 内核模块开发长期依赖于 C 语言,受限于 C 语言本身的内存安全和并发安全问题,开发复杂模块极易引入难以…...

GAN模式奔溃的探讨论文综述(一)

简介 简介:今天带来一篇关于GAN的,对于模式奔溃的一个探讨的一个问题,帮助大家更好的解决训练中遇到的一个难题。 论文题目:An in-depth review and analysis of mode collapse in GAN 期刊:Machine Learning 链接:...