JVM双亲委派与自定义类加载器

一. 类加载过程

Java Application运行前需要将编译生成的字节码文件加载到JVM中,JVM类加载过程如下:
在这里插入图片描述

1. 加载

加载阶段是类加载的第一步,在加载阶段JVM会查找并加载类的字节码文件,这个过程通常从类路径(Classpath)中查找类文件,然后将它们读入内存。

2. 验证

一旦类被加载到内存中,JVM会对字节码文件进行验证,以确保其完整性和合法性。

  1. 文件格式验证
    在这个阶段,JVM首先检查字节码文件的格式是否合法。这包括检查文件头是否以魔数开头(通常为0xCAFEBABE),以及文件版本号是否合适。

  2. 语义验证
    在这个阶段JVM会对字节码进行语义分析,确保class文件中不会存在语法错误和语义错误。

  3. 字节码验证
    这个是最复杂的一步,它检查字节码是否符合Java语言规范。这包括验证操作码是否合法,跳转指令是否正确,以及栈操作是否匹配。如果字节码验证失败,JVM会认为这个类是不安全的,并拒绝加载它

3. 准备

Java虚拟机的类准备阶段是类加载过程的重要步骤之一,它负责为类的静态变量分配内存并初始化这些变量。

4. 解析

解析阶段的主要任务:是将类或接口中的符号引用转化为直接引用。
解析过程包括以下步骤:

  1. 根据符号引用的类名找到对应的类。
  2. 验证类的可访问性和继承关系,确保访问不会违反访问控制规则。
  3. 找到符号引用对应的字段或方法,获取其内存地址或偏移量。
  4. 最终将符号引用替换为直接引用,以便在运行时直接访问类,字段或方法。
5. 初始化

初始化阶段是类加载的最后一步,它负责执行类的初始化代码。在初始化阶段,静态代码块会被执行,静态变量会被赋予初始值。

二. ClassLoader的分类

在标准的Java程序中,JVM会创建3个ClassLoader为应用程序服务。它们分别是BootStrap ClassLoader(启动类加载器),Extension ClassLoader(扩展类加载器),AppClassLoader(应用类加载器)。

  • 启动类是c++实现的,主要用于加载系统的核心类,比如rt.jar中的Java类。
  • 扩展类加载器用于加载%JAVA_HOME%/lib/ext/*.jar中的Java类。
  • 应用类加载器用于加载用户类。
import sun.net.spi.nameservice.dns.DNSNameService;public class ClassLoaderDemo {public static void main(String[] args) {// 启动类加载器ClassLoader classLoader1 =  Object.class.getClassLoader();System.out.println("Object类加载器: " + classLoader1);// ext加载器System.out.println("========================================");ClassLoader classLoader2 =  DNSNameService.class.getClassLoader();System.out.println("DNSNameService类加载器: " + classLoader2);// system加载器System.out.println("========================================");ClassLoader classLoader3 = ClassLoaderDemo.class.getClassLoader();System.out.println("ClassLoaderDemo类加载器: " + classLoader3);}
}

运行结果:

Object类加载器: null
========================================
DNSNameService类加载器: sun.misc.Launcher$ExtClassLoader@6f75e721
========================================
ClassLoaderDemo类加载器: sun.misc.Launcher$AppClassLoader@18b4aac2

双亲委派模型

JVM进行类加载时,系统会判断当前类是否被加载,如果被加载则会返回已经被加载的类;如果没有被加载则会默认先请求双亲(启动类加载器和扩展类加载器)进行加载,如果加载不成功,则会自己加载。
在这里插入图片描述
双亲委派的作用:

  • 安全性,确保程序安全,防止核心API被随意篡改。比如自己写的java.lang.String.class类是不会被加载的。

  • 避免重复加载,保证被加载类的唯一性。

下面用一段代码来演示双亲委派机制。

public class ClassLoaderDemo {public static void main(String[] args) {// 双亲委派ClassLoader classLoader1 = ClassLoaderDemo.class.getClassLoader();while (classLoader1 != null) {System.out.println(classLoader1);classLoader1 = classLoader1.getParent();}}
}

运行结果:

sun.misc.Launcher$AppClassLoader@18b4aac2
sun.misc.Launcher$ExtClassLoader@2d363fb3

双亲委派源码实现在ClassLoader类中,ClassLoader类的核心方法如下:
在这里插入图片描述
loadClass方法源码:

protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException {//加synchronized,防止多线程下重复加载synchronized (getClassLoadingLock(name)) {// 先检查类是否已被加载,findLoadedClass往下跟是调用native方法Class<?> c = findLoadedClass(name);if (c == null) {long t0 = System.nanoTime();try {//类加载器的parent属性不为空,即有父加载器if (parent != null) {//自己调自己,这里体现的是向上查找c = parent.loadClass(name, false);} else {//去启动类加载器里找,往下跟是native方法c = findBootstrapClassOrNull(name);}} catch (ClassNotFoundException e) {// ClassNotFoundException thrown if class not found// from the non-null parent class loader}//三个加载器用完了,c还是为空if (c == null) {// If still not found, then invoke findClass in order// to find the class.long t1 = System.nanoTime();//那就调用findClass方法,它是LoadClass抽象类的空方法,给子类去实现,这是自定义类加载器的切入点和扩展点c = findClass(name);// this is the defining class loader; record the statsPerfCounter.getParentDelegationTime().addTime(t1 - t0);PerfCounter.getFindClassTime().addElapsedTimeFrom(t1);PerfCounter.getFindClasses().increment();}}//resolve为false,则不执行resolveClass方法,即不要类生命周期里的连接阶段if (resolve) {resolveClass(c);}return c;}
}
三. 自定义类加载器

当JVM自带的类加载器不能满足需求时,可以自定义ClassLoader,自定义ClassLoader需要继承ClassLoader基类,并重写其中的方法,以实现对类加载过程的自定义控制。

1. 准备一个被加载的类

在D盘下新建一个Demo.java文件

package com.mooc.test;public class Demo{public Demo(){System.out.println("demo instance");}
}

将Demo.java文件编译成class文件
在这里插入图片描述

2. 自定义类加载器重写loadclass方法
package basic;import java.io.*;public class MyFileClassLoader extends ClassLoader {private String directory;public MyFileClassLoader(String directory) {this.directory = directory;}@Overrideprotected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException {// 非测试类使用父加载器if(! name.startsWith("com.mooc.test")) {return super.loadClass(name, resolve);}byte[] data = null;try {// 把类名转换为目录String file = directory + File.separator + name.replace(".", File.separator) + ".class";// 构建输入流InputStream in = new FileInputStream(file);// 构建字节输出流ByteArrayOutputStream baos = new ByteArrayOutputStream();byte[] buffer = new byte[1024];int len = -1;while ((len = in.read(buffer)) != -1) {baos.write(buffer, 0, len);}// 读取到的字节码的二进制数据data = baos.toByteArray();in.close();baos.close();return defineClass(name, data, 0, data.length);} catch (IOException e) {throw new RuntimeException(e);}}public static void main(String[] args) throws Exception {MyFileClassLoader classLoader = new MyFileClassLoader("D:");System.out.println("当前类加载器: " + classLoader);System.out.println("当前类加载器的父加载器: " + classLoader.getParent());Class clazz = classLoader.loadClass("com.mooc.test.Demo");clazz.newInstance();}
}

运行结果:

当前类加载器: basic.MyFileClassLoader@2d363fb3
当前类加载器的父加载器: sun.misc.Launcher$AppClassLoader@18b4aac2
demo instance

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Android Osmdroid + 天地图 (二)

Osmdroid 天地图 &#xff08;二&#xff09; 前言正文一、定位监听二、改变地图中心三、添加Marker四、地图点击五、其他配置① 缩放控件② Marker更换图标③ 添加比例尺④ 添加指南针⑤ 添加经纬度网格线⑥ 启用旋转手势⑦ 添加小地图 六、源码 前言 上一篇中我们显示了地图…

R语言贝叶斯分析:INLA 、MCMC混合模型、生存分析肿瘤临床试验、间歇泉喷发时间数据应用|附数据代码...

全文链接&#xff1a;https://tecdat.cn/?p38273 多模态数据在统计学中并不罕见&#xff0c;常出现在观测数据来自两个或多个潜在群体或总体的情况。混合模型常用于分析这类数据&#xff0c;它利用不同的组件来对数据中的不同群体或总体进行建模。本质上&#xff0c;混合模型是…

AI开发-计算机视觉库-OpenCV

1 需求 官网&#xff1a;OpenCV - Open Computer Vision Library 2 接口 3 示例 import cv2image cv2.imread("./data/train/1_1.jpg") print(type(image)) 4 参考资料

RK3588 C++ 多线程运行

RK3588 C 多线程 实际运行解决OpenCV问题&#xff1a; 1. OpenCV 安装 sudo apt-get update sudo apt-get install libopencv-dev2. 检查 OpenCV 安装路径 find / -name OpenCVConfig.cmake3. 设置 OpenCV_DIR 环境变量 export OpenCV_DIR/usr/lib/aarch64-linux-gnu/cmake/op…

从0开始学习机器学习--Day26--聚类算法

无监督学习(Unsupervised learning and introduction) 监督学习问题的样本 无监督学习样本 如图&#xff0c;可以看到两者的区别在于无监督学习的样本是没有标签的&#xff0c;换言之就是无监督学习不会赋予主观上的判断&#xff0c;需要算法自己去探寻区别&#xff0c;第二张…

git使用及上线流程(仅为我工作中常用)

推荐软件或者直接终端 ⚠️注意&#xff1a;在确保远程和本地分支都可使用的情况下 git常见使用命令 ls---查看所有目录 pwd---本机密码 cd 目录名---进入目录 Touch ---创建文本文件 git status---查看状态 git branch---查看分支 git pull---拉取远程最新代码 git checkou…

shell编程之变量与引用

目录 深入认识变量什么是变量变量的名称变量数据类型变量的定义自定义变量环境变量位置变量 变量赋值和作用域赋值&#xff1a;变量名变量值read从键盘读入变量值变量和引号变量的作用域变量的运算 深入认识变量 什么是变量 变量是在程序中保存用户数据的一段内存存储空间&am…

精华帖分享|浅谈金融时间序列分析与股价随机游走

本文来源于量化小论坛公共讨论区板块精华帖&#xff0c;作者为正扬&#xff0c;发布于2024年6月3日。 以下为精华帖正文&#xff1a; 01 引 时间序列分析是个很唬人的术语&#xff0c;实际上它也不是一个很容易接近的话题。我本科曾经短暂地学过一点点&#xff0c;又看到互联…

计算机网络 (4)计算机网络体系结构

前言 计算机网络体系结构是指计算机网络层次结构模型&#xff0c;它是各层的协议以及层次之间的端口的集合。这一体系结构为计算机网络及其部件应完成的功能提供了精确定义&#xff0c;并规定了这些功能应由何种硬件或软件来实现。 一、主流模型 计算机网络体系结构存在多种模型…

时钟之CSS+JS版

写在前面 此版本绘制的时钟基于CSSJS模式。 优点操作简单&#xff0c;缺点当然是不够灵活。下一篇会基于HTML5的canvas标签&#xff0c;使用JS绘制。会更灵活&#xff0c;元素更加丰富。 HTML代码 <div class"box"><article class"clock"><…

Elastic Agent:可灵活地在任何地方发送和处理任何数据

作者&#xff1a;来自 Elastic Nima Rezainia Elastic Agent 是一款功能强大且用途广泛的工具&#xff0c;可用于从各种数据源&#xff08;包括自定义用户应用程序&#xff09;收集日志和指标。现在&#xff0c;Elastic Agent 提供了无与伦比的灵活性&#xff0c;可以将数据准确…

Android CCodec Codec2 (二一)InputBuffers

CCodec使用CCodecBuffers来对输入/输出端口上的buffer进行管理&#xff0c;这一篇文章我们将一起了解InputBuffers&#xff0c;也就是输入端口的buffer管理方法。 1、CCodecBuffers CCodecBuffers是端口管理的基类&#xff0c;它抽象了输入端口管理和输出端口管理的通用方法&a…

JDBC-Mysql 时区问题详解

目录 一、前置准备 1.1 版本号列表 1.2 Sql脚本 1.3 application.yaml配置 1.4 数据库时区设置 二、java Date类型与&#xff08;jdbcType&#xff09;TIMESTAMP类型的转换 2.1 jdbc对serverTimeZone的处理 2.2 java Date转&#xff08;jdbcType&#xff09;TIMESTAMP …

LC12:双指针

文章目录 125. 验证回文串 本专栏记录以后刷题碰到的有关双指针的题目。 125. 验证回文串 题目链接&#xff1a;125. 验证回文串 这是一个简单题目&#xff0c;但条件判断自己写的时候写的过于繁杂。后面参考别人写的代码&#xff0c;首先先将字符串s利用s.toLowerCase()将其…

H5页面多个视频如何只同时播放一个?

目录 背景1. 首先介绍下 muted 属性2. 监听播放和暂停操作3. 视频播放完毕后返回桌面&#xff0c;再进入H5页面发现视频封面丢失置灰解决思路&#xff1a; 背景 页面模块同时有个四个视频模块&#xff0c;发现可以同时播放四个视频&#xff0c;但是理想的是每次只播放一个。 …

【环境配置】macOS配置jdk与maven

配置jdk与maven 配置jdk与切换java版本命令 maven安装与配置国内镜像源 用到的命令 # 进入 JDK 安装目录 cd /Library/Java/JavaVirtualMachines# 查看文件 ls ➜ jdk-1.8.jdk jdk-11.jdk# 查看路径 pwd ➜ /Library/Java/JavaVirtualMachines# 打开环境变量配置文件 vi &…

基于汇编语言的贪吃蛇程序

摘要 在我们空闲的时候&#xff0c;我们可以用一些我们学过的知识编一些东西&#xff0c;通过这些东西我们可以学习到汇编语言综合应用程序设计方法&#xff0c;还可以提高汇编语言实际应用能力&#xff0c;充分了解计算机硬件和软件&#xff0c;完成理论到实践的推进过程。这…

Qt文件目录操作

文件目录操作相关类 Qt 为文件和目录操作提供了一些类&#xff0c;利用这些类可以方便地实现一些操作。Qt 提供的与文件和目录操作相关的类包括以下几个&#xff1a; QCoreApplication&#xff1a;用于提取应用程序路径&#xff0c;程序名等文件信息&#xff1b;QFile&#x…

2024 CCF中国开源大会“开源科学计算与系统建模openSCS”分论坛成功举办

11月9日&#xff0c;2024 中国计算机学会&#xff08;CCF&#xff09;中国开源大会“开源科学计算与系统建模openSCS”分论坛在深圳落下帷幕。本次论坛由开源科学计算与系统建模工作委员会、苏州同元软控信息技术有限公司&#xff08;简称“同元软控”&#xff09;、深圳景元数…

基于 PyTorch 从零手搓一个GPT Transformer 对话大模型

一、从零手实现 GPT Transformer 模型架构 近年来&#xff0c;大模型的发展势头迅猛&#xff0c;成为了人工智能领域的研究热点。大模型以其强大的语言理解和生成能力&#xff0c;在自然语言处理、机器翻译、文本生成等多个领域取得了显著的成果。但这些都离不开其背后的核心架…