类加载机制和双亲委派

news2025/1/18 6:54:53

打印一个类加载器的示例。

import java.net.URL;
import sun.misc.Launcher;

public class TestJDKClassLoader {

    public static void main(String[] args) {

        System.out.println(String.class.getClassLoader());
        System.out.println(com.sun.crypto.provider.DESKeyFactory.class.getClassLoader().getClass().getName());
        System.out.println(TestJDKClassLoader.class.getClassLoader().getClass().getName());

        System.out.println();

        ClassLoader appClassLoader = ClassLoader.getSystemClassLoader();
        ClassLoader extClassloader = appClassLoader.getParent();
        ClassLoader bootstrapLoader = extClassloader.getParent();

        System.out.println("the bootstrapLoader : " + bootstrapLoader);
        System.out.println("the extClassloader : " + extClassloader);
        System.out.println("the appClassLoader : " + appClassLoader);

        System.out.println();
        System.out.println("bootstrapLoader加载以下文件:");
        URL[] urls = Launcher.getBootstrapClassPath().getURLs();

        for (int i = 0; i < urls.length; i++) {
            System.out.println(urls[i]);
        }
        System.out.println();

        System.out.println("extClassloader加载以下文件: ");
        System.out.println(System.getProperty("java.ext.dirs"));


        System.out.println();
        System.out.println("appClassLoader加载以下文件: ");
        System.out.println(System.getProperty("java.class.path"));

    }
}

输出结果:

null
sun.misc.Launcher$ExtClassLoader
sun.misc.Launcher$AppClassLoader

the bootstrapLoader : null
the extClassloader : sun.misc.Launcher$ExtClassLoader@1554909b
the appClassLoader : sun.misc.Launcher$AppClassLoader@18b4aac2

bootstrapLoader加载以下文件:
file:/Library/Java/JavaVirtualMachines/jdk1.8.0_361.jdk/Contents/Home/jre/lib/resources.jar
file:/Library/Java/JavaVirtualMachines/jdk1.8.0_361.jdk/Contents/Home/jre/lib/rt.jar
file:/Library/Java/JavaVirtualMachines/jdk1.8.0_361.jdk/Contents/Home/jre/lib/jsse.jar
file:/Library/Java/JavaVirtualMachines/jdk1.8.0_361.jdk/Contents/Home/jre/lib/jce.jar
file:/Library/Java/JavaVirtualMachines/jdk1.8.0_361.jdk/Contents/Home/jre/lib/charsets.jar
file:/Library/Java/JavaVirtualMachines/jdk1.8.0_361.jdk/Contents/Home/jre/lib/jfr.jar
file:/Library/Java/JavaVirtualMachines/jdk1.8.0_361.jdk/Contents/Home/jre/classes
file:/Users/wq/Library/Caches/JetBrains/IntelliJIdea2024.2/captureAgent/debugger-agent.jar

extClassloader加载以下文件: 
/Users/wq/Library/Java/Extensions:/Library/Java/JavaVirtualMachines/jdk1.8.0_361.jdk/Contents/Home/jre/lib/ext:/Library/Java/Extensions:/Network/Library/Java/Extensions:/System/Library/Java/Extensions:/usr/lib/java

appClassLoader加载以下文件: 
/Library/Java/JavaVirtualMachines/jdk1.8.0_361.jdk/Contents/Home/jre/lib/charsets.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_361.jdk/Contents/Home/jre/lib/deploy.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_361.jdk/Contents/Home/jre/lib/ext/cldrdata.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_361.jdk/Contents/Home/jre/lib/ext/dnsns.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_361.jdk/Contents/Home/jre/lib/ext/jaccess.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_361.jdk/Contents/Home/jre/lib/ext/jfxrt.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_361.jdk/Contents/Home/jre/lib/ext/localedata.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_361.jdk/Contents/Home/jre/lib/ext/nashorn.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_361.jdk/Contents/Home/jre/lib/ext/sunec.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_361.jdk/Contents/Home/jre/lib/ext/sunjce_provider.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_361.jdk/Contents/Home/jre/lib/ext/sunpkcs11.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_361.jdk/Contents/Home/jre/lib/ext/zipfs.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_361.jdk/Contents/Home/jre/lib/javaws.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_361.jdk/Contents/Home/jre/lib/jce.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_361.jdk/Contents/Home/jre/lib/jfr.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_361.jdk/Contents/Home/jre/lib/jfxswt.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_361.jdk/Contents/Home/jre/lib/jsse.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_361.jdk/Contents/Home/jre/lib/management-agent.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_361.jdk/Contents/Home/jre/lib/plugin.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_361.jdk/Contents/Home/jre/lib/resources.jar:/Library/Java/JavaVirtualMachines/jdk1.8.0_361.jdk/Contents/Home/jre/lib/rt.jar:/Users/wq/study/mianshi/jichu/demo/target/classes:/Applications/IntelliJ IDEA Ultimate.app/Contents/lib/idea_rt.jar:/Users/wq/Library/Caches/JetBrains/IntelliJIdea2024.2/captureAgent/debugger-agent.jar

类加载器

上面的类加载过程主要是通过类加载器来实现的,Java里有如下几种类加载器

引导类加载器:负责加载支撑JVM运行的位于JRE的lib目录下的核心类库,比如rt.jar、charsets.jar等。是最底层的类加载器,它使用本地代码实现,并且在Java中不可见(即通过 getParent() 方法无法获取到它

扩展类加载器:负责加载支撑JVM运行的位于JRE的lib目录下的ext扩展目录中的JAR类包

应用程序类加载器:负责加载ClassPath路径下的类包,主要就是加载你自己写的那些类

自定义加载器:负责加载用户自定义路径下的类包

双亲委派机制

在这里插入图片描述
找父亲加载,不行再由儿子自己加载

这里类加载其实就有一个双亲委派机制,加载某个类时会先委托父加载器寻找目标类,找不到再委托上层父加载器加载,如果所有父加载器在自己的加载类路径下都找不到目标类,则在自己的类加载路径中查找并载入目标类。

比如我们的Math类,最先会找应用程序类加载器加载,应用程序类加载器会先委托扩展类加载器加载,扩展类加载器再委托引导类加载器,顶层引导类加载器在自己的类加载路径里找了半天没找到Math类,则向下退回加载Math类的请求,扩展类加载器收到回复就自己加载,在自己的类加载路径里找了半天也没找到Math类,又向下退回Math类的加载请求给应用程序类加载器,应用程序类加载器于是在自己的类加载路径里找Math类,结果找到了就自己加载了。。

Math类–>应用程序类(有没有加载过)–>找扩展类加载(有没有加载过)–>引导类加载. 都找不到。
–> 引导类加载–>加载不了,扩展类加载–>加载不了,应用类加载器加载。

在这里插入图片描述

  1. Class<?> c = findLoadedClass(name);
    判断类是否加载过了,加载过了直接返回。
    2.没有加载过,
    找父加载器,为null则为引导类加载器。
    不为空则为父类加载器去加载。
    通过之前上面的打印的例子,知道ext类加载器的parent为null,app类加载器的parent为ext类加载器。
    if (parent != null) {
    c = parent.loadClass(name, false);
    } else {
    c = findBootstrapClassOrNull(name);
    }
    3. ext去加载的时候再次判断类是否加载过,没有加载过,parent==null则交给bootstrap加载器加载。
    4. bootstrap加载–>如果失败->扩展类加载–>如果失败–>应用类加载, 成功则返回。
为什么要设计双亲委派机制?

沙箱安全机制:自己写的java.lang.String.class类不会被加载,这样便可以防止核心API库被随意篡改。

避免类的重复加载:当父亲已经加载了该类时,就没有必要子ClassLoader再加载一次,保证被加载类的唯一性。

全盘负责委托机制

“全盘负责”是指当一个ClassLoder装载一个类时,除非显示的使用另外一个ClassLoder,该类
所依赖及引用的类也由这个ClassLoder载入。

自定义类加载器实现

import java.io.FileInputStream;
import java.lang.reflect.Method;

public class MyClassLoaderTest {

    static class MyClassLoader extends ClassLoader {

        private String classPath;

        public MyClassLoader(String classPath) {
            this.classPath = classPath;
        }


        @Override
        protected Class<?> findClass(String name) throws ClassNotFoundException {

            try {
                byte[] data = loadByte(name);
                //name:类名  data:字节数组(字节码文件)
                return defineClass(name , data , 0 , data.length);
            } catch (Exception e) {
                e.printStackTrace();
                throw new ClassNotFoundException();
            }

        }


        private byte[] loadByte(String name) throws Exception {
            name = name.replaceAll("\\." , "/");
            FileInputStream fis = new FileInputStream(classPath + "/" + name + ".class");
            int len = fis.available();
            byte[] data = new byte[len];
            fis.read(data);
            fis.close();
            return data;

        }
    }

    public static void main(String[] args) throws Exception {

        //初始化自定义类加载器,会先初始化父类ClassLoader,其中会把自定义类加载器的父加载
        //器设置为应用程序类加载器AppClassLoader
        MyClassLoader classLoader = new MyClassLoader("/Users/wq/study/jvm");
         // /Users/wq/study/jvm下创建 com.wq.ha.User1几级目录,将User类的复制类User1.class丢入该目录
         Class clazz = classLoader.loadClass("com.wq.ha.User1");
         Object obj = clazz.newInstance();
         Method method = clazz.getDeclaredMethod("getAge" , null);
        Object invoke = method.invoke(obj, null);
        System.out.println(invoke);
        System.out.println(clazz.getClassLoader().getClass().getName());
    }

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Mysql 搭建主从复制

Docker Mysql 镜像启动命令(主库) docker run --name mysql-master -ti -d --privileged"true" -p 3306:3306 alibaba-cloud-linux-3-registry.cn-hangzhou.cr.aliyuncs.com/alinux3/mysql_optimized:20240221-8.0.32-2.3.0 mysql_keentune.sh 修改临时密码 如果您…

OpenCV 4.10 windows 上编译并上传conan

目录 一. 上传opencv 预编译包 二. 自己手动写一个测试包并上传 三. 自己写一个app, 引用包 一. 上传opencv 预编译包 1. 下载Opencv, 并用cmake 打开 打开工程之后&#xff0c;编译&#xff0c;install&#xff0c; 目录如下 2. 准备conan 包 把Debug 和 Release 分开放 3…

CTFHub技能树-密码口令-弱口令

目录 前提知识 BrupSuite爆破的四种模式详解 解题过程 通常认为容易被别人&#xff08;他们有可能对你很了解&#xff09;猜测到或被破解工具破解的口令均为弱口令。 前提知识 BrupSuite爆破的四种模式详解 四种模式分别为&#xff1a;Sniper、Battering ram、Pitchfork、…

Visual Studio 2022从外部引入dll导致的问题

这里以我学MapGIS二次开发的一个小demo为例 一、如何引入dll 1、在解决方案资源管理器中&#xff0c;有个引用的选项 2、然后右键点击添加引用 点击之后会出现如下&#xff1a; 3、点击浏览选项&#xff0c;选择想要引入dll的路径&#xff0c;这里我选择下载MapGIS 10的路径 …

[LitCTF 2024]SAS - Serializing Authentication

题目提示反序列化 源码 <?phpclass User {public $username;public $password;function __construct($username, $password) {$this->username $username;$this->password $password;}function isValid() { return $this->username admin && $this-&g…

《JavaEE进阶》----17.<Mybatis基本操作【注解XML】>

本篇博客详细讲解了&#xff1a;编写SQL语句 1.使用注释 2.使用XML 3.多表查询 前言&#xff1a; Mybatis规范中方法名不能重复&#xff0c;即便参数不同。因为每一个方法名都是有一个唯一的ID标识的。因此不能重复。 我们会将数据库相关的接口放在Mapper包下面。 对&#xff0…

Latex输入数学期望E及花体符号方法

一、数学期望 E \mathbb{E} E 使用Latex写论文时&#xff0c;我们希望输入如下图所示的数学期望&#xff1a; 方法如下&#xff1a; 首先需要导入\usepackage{amssymb}包&#xff0c;然后正文使用描述为\mathbb{E} 二、花体 B \mathcal{B} B 此外&#xff0c;当我们希望…

外贸获客:主动开发有用吗?

今天主要和大家聊聊&#xff0c;做外贸几个常用的获客渠道。 开发客户的渠道大体上分两种&#xff1a;1、主动开发&#xff1b;2、被动询盘 我们一一进行解析。1、社交媒体开发 即利用社交媒体&#xff0c;如Youtube、LinkedIn、Instagram、TikTok、Facebook等平台进行客户开发…

30道软件测试基础面试题!(含答案)

1、你的测试职业发展是什么&#xff1f; 测试经验越多&#xff0c;测试能力越高。所以我的职业发展是需要时间积累的&#xff0c;一步步向着高级测试工程师奔去。而且我也有初步的职业规划&#xff0c;前 3 年积累测试经验&#xff0c;按如何做好测试工程师的要点去要求自己&a…

JS Reflect 对象 — 深度解析

JS Reflect 对象 — 深度解析 在JavaScript的广阔天地里&#xff0c;Reflect对象如同一面明镜&#xff0c;映射出底层语言操作的精髓。作为前端开发者&#xff0c;掌握Reflect对象及其相关API&#xff0c;无疑能够提升我们的编程技艺&#xff0c;让代码更加简洁、高效。接下来&…

AV1 Bitstream Decoding Process Specification--[1]:术语和定义

原文地址&#xff1a;https://aomediacodec.github.io/av1-spec/av1-spec.pdf没有梯子的下载地址&#xff1a;AV1 Bitstream & Decoding Process Specification摘要&#xff1a;这份文档定义了开放媒体联盟&#xff08;Alliance for Open Media&#xff09;AV1视频编解码器…

浅谈C++入门(1)

​ &#x1f339;个人主页&#x1f339;&#xff1a;喜欢草莓熊的bear &#x1f339;专栏&#x1f339;&#xff1a;C入门 目录 前言 一、C的第一个程序 二、 命名空间 2.1 namespace的价值 2.2 namesapce的定义&#xff08;这里一些东西以记住加理解为主&#xff09; 2.…

国产服务器CPU发展分析

CPU行业概览&#xff1a;信创带动服务器CPU国产化 目前CPU行业由两大生态体系主导&#xff1a;一是基于X86指令系统和Windows操作系统的Wintel体系&#xff0c;主要用于服务器与电脑等&#xff1b;二是基于ARM指令系统和Android操作系统的AA体系&#xff0c;主要用于移动设备…

数据结构加餐:三路划分、自省排序、文件归并排序

数据结构加餐1 1.快排之三路划分2.快排之自省排序3.文件归并排序3.1外排序3.2归并排序的实现3.2.1归并排序思想3.2.2文件归并排序代码实现 1.快排之三路划分 在之前完成的快排仍然存在这一些问题&#xff0c;当重复数据较多时&#xff0c;快速排序选择的基值也会较不恰当&#…

SaaS化多租户实现的两种方法

SaaS化多租户实现的两种方法 SaaS系统的定义 SaaS&#xff0c;全称为Software-as-a-Service&#xff08;软件即服务&#xff09;&#xff0c;是一种基于云计算的软件交付模式。而SaaS系统&#xff0c;即是通过这种模式提供给用户的软件系统。即多租户系统&#xff0c;每个租户…

MySQL 日志篇:Redo 文件和自适应检查点

MySQL 的 InnoDB 存储引擎使用 Redo Log 记录事务对数据的更改&#xff0c;以便在系统崩溃恢复时能够重做这些更改&#xff0c;从而保证事务的持久性。对于产生的 Redo Log&#xff0c;InnoDB 存储引擎首先将其写入内存中的 Log Buffer&#xff0c;随后再将 Log Buffer 中的 Re…

力扣337-打家劫舍 III(Java详细题解)

题目链接&#xff1a;337. 打家劫舍 III - 力扣&#xff08;LeetCode&#xff09; 前情提要&#xff1a; 本体是打家劫舍的一个变形题&#xff0c;希望大家能先做198. 打家劫舍 - 力扣&#xff08;LeetCode&#xff09;&#xff0c;并看一下我上题的讲解力扣198-打家劫舍&…

【刷题】Day 3--错误的集合

hello&#xff01;又见面啦~~~ 一道习题&#xff0c;要长脑子了...... 【. - 力扣&#xff08;LeetCode&#xff09;】 【思路】 /*** Note: The returned array must be malloced, assume caller calls free().*/void Bubble_sort(int arr[], int size) {int temp;for (int i…

多速率信号处理-CIC滤波器

基本原理 级联积分梳状滤波器&#xff08;Cascade Intergrator Comb&#xff09;是多速率信号处理中一种十分高效的数字滤波器。CIC滤波器具有低通滤波器的特性&#xff0c;同时具有以下优势&#xff1a; 滤波器系数全为1&#xff0c;设计时不需要存储滤波器系数&#xff0c;…

拖放WORD文件朗读全文

把WORD拖放到tkinter的窗口&#xff0c;就可以朗读整改word文件的内容。 代码&#xff1a; # -*- coding: utf-8 -*- """ Created on Tue Sep 10 17:09:35 2024author: YBK """ import pyttsx3 import comtypes.client import os import tkint…