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

二、Java虚拟机的基本结构

Java虚拟机的架构

  • 1.内存结果概述
  • 2.类加载器子系统的作用
  • 3. 类加载器ClassLoader角色
  • 4.类的加载过程
  • 5.类加载器的分类
    • 1.引导类加载器(虚拟机自带的加载器)Bootstrap ClassLoader
    • 2.扩展类加载器(虚拟机自带的加载器) Extenssion ClassLoader
    • 3.应用程序类加载器(虚拟机自带的加载器)AppClassLoader
    • 4.用户自定义类加载器
    • 5.关于ClassLoader

1.内存结果概述

Java虚拟机那么复杂,它的基本结构是什么?各个组成部分有何作用?又是如何相互协调工作的呢?要解答这些问题就必须先了解Java堆、Java栈、永久区和元数据区的基本概念。
在这里插入图片描述

在这里插入图片描述在这里插入图片描述

![在这里插入图片描述](https://img-blog.csdnimg.cn/e72bd95094bc4af1bb277a4ae5687474.jpeg

2.类加载器子系统的作用

1.类加载器子系统负责从文件或网络中加载Class文件,class文件在文件的开头有特定的文件标识。
2.ClassLoader只负责class文件的加载,至于类是否可运行,则有ExectionEngine决定。
3.加载的类的信息存放于一个称为方法区的内存空间,除了类的信息外,方法区中还会存放运行时常量池信息,可能还包括字符串字面量和数字常量(这部分常量信息是Class文件中常量池部分的内存映射)

3. 类加载器ClassLoader角色

1.class file 存在于本地硬盘上,可以理解为设计师画在纸上的模板,而最终这个模板在执行的时候是要加载到jvm当中来根据这个文件实例 化出n个一模一样的实例。
2.class文件加载到JVM中,被称为DNA元数据模板,放在方法区。
3.在类文件.class文件到->JVM->元数据模板,此过程就需要一个运输工具,类装载器Class Loader,扮演着一个快递元的身份。

在这里插入图片描述
在这里插入图片描述
恶意攻击有可能对字节码文件进行修改。

4.类的加载过程

在这里插入图片描述
加载:
1.通过一个类的全限定命名获取定义此类的二进制字节流
2. 将这个字节流代表的静态存储结构转化为方法区的运行时数据结构
3. 在内存中生成一个代表这给类的java.lang.Class对象,做为方法区这个类的各种数据访问入口。
加载.class的方式
1.从本地系统中获取。
2.从网络中获取。典型场景:Web Applet。
3.从zip压缩包中获取,称为日后jar,war格式的基础。
4.运行时计算生成,典型的场景:jsp应用
5.从专有数据库中提取.class文件
6.从加密文件中获取,典型的防Class文件被反编译的保护措施.

验证(Verify):
1.目的在于确保Class文件的字节流中包含的符号信息符合虚拟机的要求,保证被加载类的正确性,不会危害虚拟机的自身安全。
2.主要包含四种验证:文件格式的验证,元数据验证,字节码验证,符号引用验证。
准备(Prepare):
1.为类变量分配内存并设置默认初始值,即零值。
2.这里不包含final修饰的static,因为final在编译的时候就会分配了,准备阶段会显示初始化。
3.这里不会为实例变量分配初始化,类变量会分配在方法去中,而实例变量是会随着对象一起分配到java堆内存中。
解析(Resolve):
1.将常量池内的符号引用转换为直接引用的过程。
2.事实上,解析操作往往会伴随着Java虚拟机在执行完初始之后再执行。
3.符号引用就是一组符号用来描述所有引用的目标。符号引用的字面量形式明确定义在<java虚拟机规范>的class文件格式中,直接引用就是直接指向目标的指针,相对的偏移量或一个间接定位到目标的句柄。
4.解析动作主要针对类或接口、字段、类方法、接口方法、方法类型等。对应常量池中的CONSTANT_CLASS_info、CONSTANT_Fieldref_info、CONSTANT_Methoftrf_info等。
初始化:
1.初始化阶段几十执行类构造器方法()的过程
2.此方法不需要定义,是javac编译器自收集类中所有类变量的赋值动作和静态代码块中的语句合并起来。
3.构造器方法中指令按语句在源文件中出现的顺序执行。
4.()不同于类的构造器
5.若该类具有父类,jvm会保证子类()执行前,父类的()已经执行完毕。
6.虚拟机必须保证一个类的()方法在多线程下被同步加锁。
在这里插入图片描述
若类中没有静态变量或静态代码块,类构造器方法()就不会生成。
任何一个类声明以后,内部至少存在一个类构造器()
在这里插入图片描述
IDEA安装jclasslib Bytecos Viewer插件可以查看编译后的字节码文件内容,插件安装后重启IDEA
在这里插入图片描述
查看编译后的字节码文件
在这里插入图片描述

在这里插入图片描述
下面代码的执行顺序为:ClassInintTest类加载完成—>调用静态方法main()–>调用Son—>加载并初始化Father—>加载并初始化Son—>结果等于2
在这里插入图片描述
先引入A值,再引入B值
在这里插入图片描述

5.类加载器的分类

1.JVM支持两种类型的类加载器,分别为引导类加载器(Bootstrap ClassLoader) 和自定义类加载器(User-Defind ClassLoader).(JAVA的核心类库都是引导类加载器加载的)
2.从概念上来讲,自定义类加载器以一般指的是程序中由开发人员自定义的一类类加载器,但是Java虚拟机规范并没有这么定义,而是将所有派生出来的抽象类ClassLoader的类加载器都划分为自定义类加载器。
3.无论类加载器的类型如何划分,在程序中我们最常见的类加载器始终只有3个:

1.引导类加载器(虚拟机自带的加载器)Bootstrap ClassLoader

1.这个类加载使用C/C++的语言实现的,嵌套在JVM内部。
2.它用来加载Java的核心类库,(JAVA_HOME/jre/lib/rt.jar resources.jar 或sun,boot.class.path路径下的内容),用于提供JVM自身需要的类.
3.并不继承自java.lang.ClassLoader,没有父加载器。
4.加载扩展类和应用程序类加载器,并指定为他们的父类加载器。
5.出于安全考虑,Bootstrap 启动类加载器只加载名为Java、javax、sun等开头的类。

获取BootstrapClassLoader能够加载的api路径
在这里插入图片描述

2.扩展类加载器(虚拟机自带的加载器) Extenssion ClassLoader

1.Java语言编写,由sun.misc.Launcher$ExtClassLoader实现。
2.派生于ClassLoader类
3.父类加载器为启动类加载器。
4.从java.ext.dirs系统属性锁指定的目录中加载类库,或从JDK的安装目录的jre/lib.ext子目录(扩展目录)下载类库,如果用户创建的JAR放在此目录下,也会自动i用由扩展类加载器加载。
在这里插入图片描述

3.应用程序类加载器(虚拟机自带的加载器)AppClassLoader

1.java语言编写,由sun.misc.LauncherAppClassLoader实现。2.派生于ClassLoader类。3.父类加载器为扩展类加载器。4.它负责加载环境变量classpath或系统属性,java.class.path指定路径下的类库。5.该类加载器是程序中默认的类加载器,一般来说,Java应用的类都是由它来完成加载。6.通过ClassLoaderAppClassLoader实现。 2.派生于ClassLoader类。 3.父类加载器为扩展类加载器。 4.它负责加载环境变量classpath或系统属性,java.class.path指定路径下的类库。 5.该类加载器是程序中默认的类加载器,一般来说,Java应用的类都是由它来完成加载。 6.通过ClassLoaderAppClassLoader实现。2.派生于ClassLoader类。3.父类加载器为扩展类加载器。4.它负责加载环境变量classpath或系统属性,java.class.path指定路径下的类库。5.该类加载器是程序中默认的类加载器,一般来说,Java应用的类都是由它来完成加载。6.通过ClassLoadergetSystemClassLoader()方法可以获取到该类加载器。

4.用户自定义类加载器

在java的日常应用程序开发中,类加载器几乎是由上述3中类加载器相互配合执行的,在必要=时,我们还可以自定义类加载器,来定制类的加载方式。

为什么要用自定义类加载器呢。
1.隔离加载类(例如系统jar包与中间jar不冲突,由于可能存在类冲突,未必免冲突)
2.修改类加载的方(除了引导类加载器BootstrapLoader加载所需的核心类之外有些类不是必须的,可以等到需要用的时候在引入)
3.扩展加载源(加载的类可以是本地的物理磁盘也可以是网络或者数据库等其他方式加载字节码文件来源)
4.防止源码泄露

用户自定义类加载器实现的步骤:
1.开发人员可以通过继承抽象类java.lang.ClassLoader类的方式,实现直自己的类加载器,以满足一些特殊的需求。
2.在JDK1.2之前,在自定义类加载器时,总会取继承ClassLoader类并重些写loadClass()方法,从而实现自定义类加载,但是在JDK1.2之后
已不再建议用户去覆盖loadClass()方法,而是建议把自定义的类加载逻辑写再findClass()方法中。
3.在编写自定义类加载器时,如过没有太过于复杂的需求,可以直接继承URLClassLoader类。这样就可以避免自己去编写findClass()方法及其获取字节码流的方式,使自定义类加载器编写更简洁。

import java.io.FileNotFoundException;public class CustomClassLoader extends ClassLoader {@Overrideprotected Class<?> findClass(String name) throws ClassNotFoundException {try {byte[] result = getClassFromCustomPath(name);if (result == null) {throw new FileNotFoundException();} else {return defineClass(name, result, 0, result.length);}} catch (FileNotFoundException e) {e.printStackTrace();}throw new ClassNotFoundException(name);}private byte[] getClassFromCustomPath(String name){//从自定义路径中加载指定类:细节略//如果指定路径的字节码文件进行了加密,则需要在此方法中进行解密操作。return null;}public static void main(String[] args) {CustomClassLoader customClassLoader = new CustomClassLoader();try {Class<?> clazz = Class.forName("One",true,customClassLoader);Object obj = clazz.newInstance();System.out.println(obj.getClass().getClassLoader());} catch (Exception e) {e.printStackTrace();}}
}

5.关于ClassLoader

ClassLoader类,它是一个抽象类,其后所有的类加载器都继承自ClassLoader(不包括启动类加载器)
getParent(); 返回该类加载器的超类加载器。
loadClass(String name) 加载名称为name的类,返回结果为java.lang.Class类的实例。
findClass(String name) 查找名称为name的类,返回结果为java.lang.Class类的实例。
findLoadedClass(String name) 查找名称为name的已经被加载过的类,返回结果为java.lang.Class类的实例。
defindClass(String name ,bytr[] b,int off,int len) 把字节数组b中的内容转换为一个Java类,返回结果为java.lang.Class类的实例,
resolveClass(Class<?> c) 链接一个指定的java类。

相关文章:

二、Java虚拟机的基本结构

Java虚拟机的架构1.内存结果概述2.类加载器子系统的作用3. 类加载器ClassLoader角色4.类的加载过程5.类加载器的分类1.引导类加载器(虚拟机自带的加载器)Bootstrap ClassLoader2.扩展类加载器(虚拟机自带的加载器) Extenssion ClassLoader3.应用程序类加载器(虚拟机自带的加载器…...

华为OD机试 - 用户调度(Python) | 机试题+算法思路+考点+代码解析 【2023】

用户调度 题目 在通信系统中有一个常见的问题是对用户进行不同策略的调度,会得到不同系统消耗的性能。 假设由N个待串行用户,每个用户可以使用A/B/C三种不同的调度策略。 不同的策略会消耗不同的系统资源,请你根据如下规则进行用户调度,并返回总的消耗资源数。 规则是: …...

HashMap(JDK1.8)源码+底层数据结构分析

HashMap 简介底层数据结构分析 JDK1.8 之前JDK1.8 之后 HashMap 源码分析 构造方法put 方法get 方法resize 方法 HashMap 常用方法测试 感谢 changfubai 对本文的改进做出的贡献&#xff01; HashMap 简介 HashMap 主要用来存放键值对&#xff0c;它基于哈希表的 Map 接口实现…...

case的使用

1.x和z值 1.1.定义 x&#xff1a;表示不定值 z&#xff1a;表示高阻态&#xff0c;还有一种表达方式“&#xff1f;” 一个x/z可以用来定义十六进制&#xff08;h&#xff09;数的4位二进制的状态&#xff0c;八进制&#xff08;o&#xff09;数的3位&#xff0c;二进制&#x…...

Mac配置ITerm2

Mac配置ITerm2 install-shell-integration配置lrzsz配置zsh安装Oh-My-Zsh修改皮肤文件加载皮肤添加插件配置profiles 1.expect配置文件2.shell脚本 iterm2顶部白条闪烁 install-shell-integration 安装完成之后会有一个指示标&#xff0c;需要弄掉Preferences > Profiles …...

JUC并发编程(下)

✨作者&#xff1a;猫十二懿 ❤️‍&#x1f525;账号&#xff1a;CSDN 、掘金 、个人博客 、Github &#x1f389;公众号&#xff1a;猫十二懿 学习地址 写在最前 JUC并发编程&#xff08;上&#xff09; JUC&#xff08;Java Util Concurrent&#xff09;学习内容框架&…...

API接口的基础知识

API是应用程序编程接口&#xff08;Application Programming Interface&#xff09;的缩写&#xff0c;能够起到两个软件组件之间的连接器或中介的作用。此类接口往往通过一组明确的协议&#xff0c;来表示各种原始的请求和响应。API文档可以向开发人员展示请求和响应是如何形成…...

基于Spring Boot的教务管理系统

文章目录项目介绍主要功能截图&#xff1a;登录首页学生信息管理班级信息管理教师信息管理教师评价部分代码展示设计总结项目获取方式&#x1f345; 作者主页&#xff1a;Java韩立 &#x1f345; 简介&#xff1a;Java领域优质创作者&#x1f3c6;、 简历模板、学习资料、面试题…...

网页扫描图像并以pdf格式上传到服务器端

本文描述如何通过网页驱动扫描仪、高拍仪等图像扫描设备进行图像扫描&#xff0c;扫描结果经编辑修改后以pdf压缩格式上传到后台java程序中进行服务器端落盘保存。图像扫描上传如文字描述顺序所介绍&#xff0c;先要驱动扫描设备工作&#xff0c;进行纸张数据的光学扫描操作形成…...

Airbyte入门

Airbyte 后端技术栈Java 17框架&#xff1a;JerseyAPI&#xff1a; OAS3数据库&#xff1a;PostgreSQL单元和E2E测试&#xff1a;JUnit 5编排&#xff1a;Temporal连接器技术栈连接器可以用任何语言编写。但是&#xff0c;最常见的语言是&#xff1a;Python3.9.0Java 17前端技术…...

研究人员在野外发现大量的信息窃取者 “Stealc “的样本

一个名为Stealc的新信息窃取者正在暗网上做广告&#xff0c;它可能成为其他同类恶意软件的一个值得竞争的对象。 "SEKOIA在周一的一份报告中说&#xff1a;"威胁行为者将Stealc作为一个功能齐全、随时可用的窃取者&#xff0c;其开发依赖于Vidar、Raccoon、Mars和Re…...

数据结构——复杂度讲解(2)

作者&#xff1a;几冬雪来 时间&#xff1a;2023年2月22日 内容&#xff1a;数据结构复杂度讲解 目录 前言&#xff1a; 复杂度讲解&#xff08;2&#xff09;&#xff1a; 1.空间复杂度是什么&#xff1a; 2.空间复杂度讲解&#xff1a; 结尾&#xff1a; 前言&#x…...

【LeetCode】任务调度器 [M](贪心)

621. 任务调度器 - 力扣&#xff08;LeetCode&#xff09; 一、题目 给你一个用字符数组 tasks 表示的 CPU 需要执行的任务列表。其中每个字母表示一种不同种类的任务。任务可以以任意顺序执行&#xff0c;并且每个任务都可以在 1 个单位时间内执行完。在任何一个单位时间&…...

Spring代理模式——静态代理和动态代理

✅作者简介&#xff1a;2022年博客新星 第八。热爱国学的Java后端开发者&#xff0c;修心和技术同步精进。 &#x1f34e;个人主页&#xff1a;Java Fans的博客 &#x1f34a;个人信条&#xff1a;不迁怒&#xff0c;不贰过。小知识&#xff0c;大智慧。 &#x1f49e;当前专栏…...

Anaconda和PyCharm的一些安装问题和命令

今天更新了Windows上的Anaconda到2.3.2&#xff0c;PyCharm到2022.3。 ——发现是纯纯的犯贱orz。出了一堆问题。在这里记录一下供后来者参考。 Anaconda安装 将.\anaconda3\Scripts 和.\anaconda3\Library\bin添加到系统环境变量中。 新建环境的目录在.\anaconda3\envs下 N…...

sql优化建议

对查询进行优化&#xff0c;应尽量避免全表扫描&#xff0c;首先应考虑在 where 及 order by 涉及的列上建立索引。 应尽量避免在 where 子句中使用!或<>操作符&#xff0c;否则将引擎放弃使用索引而进行全表扫描。 应尽量避免在 where 子句中对字段进行 null 值判断&a…...

google hacker语句

哎&#xff0c;我就是沾边&#xff0c;就是不打实战(&#xffe3;o&#xffe3;) . z Z 文章目录前言一、什么是谷歌Docker&#xff1f;二、受欢迎的谷歌docker语句谷歌docker的例子日志文件易受攻击的 Web 服务器打开 FTP 服务器SSH私钥电子邮件列表实时摄像机MP3、电影和 PDF…...

Spring AOP

Spring AOP 文章目录Spring AOP1.概念1.面向切面编程2.AOP的目的3.AOP实现的分类4.AOP 术语2. Spring AOP的特性1.能力与目标2.AOP机制1.理解SpringAOP的代理2.AOP代理类的自调用代码的粒度如何让自调用走代理&#xff1f;3.Enabling AspectJ Support3. 定义切面与切点1. 声明切…...

【消费战略方法论】认识消费者的恒常原理(一):消费者稳态平衡原理

“消费战略”是塔望咨询基于大量的战略与营销实践经验结合心理学、经济学、传播学等相关专业学科的知识应用进行提炼与创造形成的战略方法体系。消费战略强调以消费者为导向&#xff0c;进行企业、品牌战略、品牌营销的制订和落地&#xff0c;企业经营的每个环节和输出的每个动…...

python居然能语音控制电脑壁纸切换,只需60行代码

前言 嗨喽~大家好呀&#xff0c;这里是魔王呐 ❤ ~! 家在日常的电脑使用中&#xff0c;都会有自己喜爱类型的桌面 单纯的桌面有时候会让人觉得单调 今天&#xff0c;就由我带领大家只用60行代码打造一款语音壁纸切换器程序&#xff0c; 让大家能够通过语音的方式来控制电脑去…...

Python爬虫实战:研究MechanicalSoup库相关技术

一、MechanicalSoup 库概述 1.1 库简介 MechanicalSoup 是一个 Python 库,专为自动化交互网站而设计。它结合了 requests 的 HTTP 请求能力和 BeautifulSoup 的 HTML 解析能力,提供了直观的 API,让我们可以像人类用户一样浏览网页、填写表单和提交请求。 1.2 主要功能特点…...

进程地址空间(比特课总结)

一、进程地址空间 1. 环境变量 1 &#xff09;⽤户级环境变量与系统级环境变量 全局属性&#xff1a;环境变量具有全局属性&#xff0c;会被⼦进程继承。例如当bash启动⼦进程时&#xff0c;环 境变量会⾃动传递给⼦进程。 本地变量限制&#xff1a;本地变量只在当前进程(ba…...

【OSG学习笔记】Day 18: 碰撞检测与物理交互

物理引擎&#xff08;Physics Engine&#xff09; 物理引擎 是一种通过计算机模拟物理规律&#xff08;如力学、碰撞、重力、流体动力学等&#xff09;的软件工具或库。 它的核心目标是在虚拟环境中逼真地模拟物体的运动和交互&#xff0c;广泛应用于 游戏开发、动画制作、虚…...

k8s从入门到放弃之Ingress七层负载

k8s从入门到放弃之Ingress七层负载 在Kubernetes&#xff08;简称K8s&#xff09;中&#xff0c;Ingress是一个API对象&#xff0c;它允许你定义如何从集群外部访问集群内部的服务。Ingress可以提供负载均衡、SSL终结和基于名称的虚拟主机等功能。通过Ingress&#xff0c;你可…...

Cesium1.95中高性能加载1500个点

一、基本方式&#xff1a; 图标使用.png比.svg性能要好 <template><div id"cesiumContainer"></div><div class"toolbar"><button id"resetButton">重新生成点</button><span id"countDisplay&qu…...

线程与协程

1. 线程与协程 1.1. “函数调用级别”的切换、上下文切换 1. 函数调用级别的切换 “函数调用级别的切换”是指&#xff1a;像函数调用/返回一样轻量地完成任务切换。 举例说明&#xff1a; 当你在程序中写一个函数调用&#xff1a; funcA() 然后 funcA 执行完后返回&…...

STM32F4基本定时器使用和原理详解

STM32F4基本定时器使用和原理详解 前言如何确定定时器挂载在哪条时钟线上配置及使用方法参数配置PrescalerCounter ModeCounter Periodauto-reload preloadTrigger Event Selection 中断配置生成的代码及使用方法初始化代码基本定时器触发DCA或者ADC的代码讲解中断代码定时启动…...

linux arm系统烧录

1、打开瑞芯微程序 2、按住linux arm 的 recover按键 插入电源 3、当瑞芯微检测到有设备 4、松开recover按键 5、选择升级固件 6、点击固件选择本地刷机的linux arm 镜像 7、点击升级 &#xff08;忘了有没有这步了 估计有&#xff09; 刷机程序 和 镜像 就不提供了。要刷的时…...

Keil 中设置 STM32 Flash 和 RAM 地址详解

文章目录 Keil 中设置 STM32 Flash 和 RAM 地址详解一、Flash 和 RAM 配置界面(Target 选项卡)1. IROM1(用于配置 Flash)2. IRAM1(用于配置 RAM)二、链接器设置界面(Linker 选项卡)1. 勾选“Use Memory Layout from Target Dialog”2. 查看链接器参数(如果没有勾选上面…...

Python爬虫(二):爬虫完整流程

爬虫完整流程详解&#xff08;7大核心步骤实战技巧&#xff09; 一、爬虫完整工作流程 以下是爬虫开发的完整流程&#xff0c;我将结合具体技术点和实战经验展开说明&#xff1a; 1. 目标分析与前期准备 网站技术分析&#xff1a; 使用浏览器开发者工具&#xff08;F12&…...