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加载完之后,通过初始化阶段触发了驱动类的加载,类的加载依然遵循双亲委派机制。

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

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

VScode如何使用deepseek详细教程

本章教程,主要介绍如何在vscode中,安装使用deepseek教程。deepseek生成式人工智能模型最近可是非常的热门。感兴趣的可以尝试看看吧。 一、注册deepseek账号 注册登录地址:https://platform.deepseek.com/api_keys 注册登录账号之后,创建一个API key ,将这个API key复制下…

大数据相关职位介绍之三(数据挖掘,数据安全 ,数据合规师,首席数据官,数据科学家 )

大数据相关职位介绍之三(数据挖掘,数据安全 ,数据合规师,首席数据官,数据科学家 ) 文章目录 大数据相关职位介绍之三(数据挖掘,数据安全 ,数据合规师,首席数据…

[基础]端口隔离实验

实验教程 隔离类型 双向隔离:统一端口隔离组的接口之间隔离,不同端口隔离组的接口之间不隔离,端口隔离只针对同一设备上的端口隔离组成员,对于不同设备上的接口而言无法实现。单向隔离:实现不同端口隔离组的接口之间的…

vscode 如何通过Continue引入AI 助手deepseek

第一步: 在deepseek 官网上注册账号,得到APIKeys(deepseek官网地址) 创建属于自己的APIKey,然后复制这个key,(注意保存自己的key)! 第二步: 打开vscode,在插件市场安装Continue插件, 点击设置,添加deepseek模型,默认…

FPGA的IP核接口引脚含义-快解

疑问 手册繁琐,怎样快速了解IP核各输入输出接口引脚的含义。 答疑 不慌不慌,手册确实比较详细但繁琐,如何快速知晓该部分信息,涛tao道长给你们说,简单得很,一般新入门的道友有所不知,往往后面…

“AI隐患识别系统,安全多了道“智能护盾”

家人们,在生活和工作里,咱们都知道安全那可是头等大事。不管是走在马路上,还是在工厂车间忙碌,又或是住在高楼大厦里,身边都可能藏着一些安全隐患。以前,发现这些隐患大多靠咱们的眼睛和经验,可…

RocketMQ中的NameServer主要数据结构

1.前言 NameServer是RocketMQ中的一个比较重要的组件,我们这篇博客针对NameSever中包含的组件进行分析,分析一下NameServer中包含的组件以及组件的作用。以前我有一篇博客中rocketMq源码分析之搭建本地环境-CSDN博客,在这篇博客中就简单看了…

8-登录流程

在AppStartInitFinish_CreateLoginUI.初始化后,执行Login界面的初始化 登录面板逻辑:UILoginComponentSystem,针对组件UILoginComponent创建的System 登录面板逻辑:UILoginComponent 逻辑层: LoginHelper中的clientSenderComponent.LoginA…

基于HAI部署DeepSeekR1的招标文书智能辅助生产开发与应用

一、前言 1.1行业背景 在日常商业活动中,招投标流程往往是企业竞标和项目落地的关键一环。其中,招标文书的编写工作对于投标企业极具挑战:既要保证逻辑清晰、条理分明,又必须遵循招标机构的各类格式规范,甚至还有特定…

SQL/Panda映射关系

Pandas教程(非常详细)_pandas 教程-CSDN博客 SQL:使用SELECT col_1, col_2 FROM tab; Pandas:使用df[[col_1, col_2]]。 SQL:使用SELECT * FROM tab WHERE col_1 11 AND col_2 > 5; Pandas:使用df…

Sentinel的安装和做限流的使用

一、安装 Release v1.8.3 alibaba/Sentinel GitHubA powerful flow control component enabling reliability, resilience and monitoring for microservices. (面向云原生微服务的高可用流控防护组件) - Release v1.8.3 alibaba/Sentinelhttps://github.com/alibaba/Senti…

院校联合以项目驱动联合培养医工计算机AI人才路径探析

一、引言 1.1 研究背景与意义 在科技飞速发展的当下,医疗人工智能作为一个极具潜力的新兴领域,正深刻地改变着传统医疗模式。从疾病的早期诊断、个性化治疗方案的制定,到药物研发的加速,人工智能技术的应用极大地提升了医疗服务…

Hot100之矩阵

73矩阵置零 题目 思路解析 收集0位置所在的行和列 然后该行全部初始化为0 该列全部初始化为0 代码 class Solution {public void setZeroes(int[][] matrix) {int m matrix.length;int n matrix[0].length;List<Integer> list1 new ArrayList<>();List<…

w186格障碍诊断系统spring boot设计与实现

&#x1f64a;作者简介&#xff1a;多年一线开发工作经验&#xff0c;原创团队&#xff0c;分享技术代码帮助学生学习&#xff0c;独立完成自己的网站项目。 代码可以查看文章末尾⬇️联系方式获取&#xff0c;记得注明来意哦~&#x1f339;赠送计算机毕业设计600个选题excel文…

ASP.NET Core JWT

目录 Session的缺点 JWT&#xff08;Json Web Token&#xff09; 优点&#xff1a; 登录流程 JWT的基本使用 生成JWT 解码JWT 用JwtSecurityTokenHandler对JWT解码 注意 Session的缺点 对于分布式集群环境&#xff0c;Session数据保存在服务器内存中就不合适了&#…

Axure大屏可视化动态交互设计:解锁数据魅力,引领决策新风尚

可视化组件/模板预览&#xff1a;Axure 一、大屏可视化技术概览 在数据驱动决策的时代&#xff0c;大屏可视化技术凭借直观、动态的展示方式&#xff0c;已成为众多行业提升管理效率和优化决策过程的关键工具。它能够将复杂的数据转化为易于理解的图形和动画&#xff0c;帮助…

网络工程师 (20)计算机网络的概念

一、定义 计算机网络是指将地理位置不同、具有独立功能的多台计算机及其外部设备&#xff0c;通过通信线路及通信设备连接起来&#xff0c;在网络操作系统、网络管理软件及网络通信协议的管理和协调下&#xff0c;实现信息传递和资源共享的计算机通信系统。 二、组成 资源子网&…

Android TabLayout 使用进阶(含源码)

android:layout_height“match_parent” android:orientation“vertical” tools:context“.mode2.ClassificationActivity”> <com.google.android.material.tabs.TabLayout android:id“id/tab_layout” android:layout_width“match_parent” android:layout_he…

【算法应用】Alpha进化算法求解二维栅格路径规划问题

目录 1.算法原理2.二维路径规划数学模型3.结果展示4.参考文献5.代码获取 1.算法原理 Alpha进化&#xff1a;一种具有进化路径自适应和矩阵生成的高效进化算法 2.二维路径规划数学模型 栅格法模型最早由 W.E. Howden 于 1968 年提出&#xff0c;障碍物的栅格用黑色表示&#…

机器学习--1.KNN机器学习入门

1、机器学习概述 1.1、什么是机器学习 机器学习&#xff08;Machine Learning&#xff09;是人工智能&#xff08;Artificial Intelligence&#xff09;领域的一个子集&#xff0c;它主要关注如何让计算机系统通过经验学习&#xff08;数据&#xff09;并自动改进性能。机器学…