广告
返回顶部
首页 > 资讯 > 后端开发 > Python >Java中如何自定义一个类加载器
  • 402
分享到

Java中如何自定义一个类加载器

Java自定义类加载器自定义类加载器Java类加载器 2022-11-21 22:11:19 402人浏览 泡泡鱼

Python 官方文档:入门教程 => 点击学习

摘要

目录如何自定义加载器?示例:读取某文件的下的某class文件类加载器的使用及自定义类加载器如何自定义加载器? 1.创建一个自定义加载器类 继承 ClassLoader 类 2.重写

如何自定义加载器?

1.创建一个自定义加载器类 继承 ClassLoader 类

2.重写 findClass 方法。 主要是实现从那个路径读取 jar包或者.class文件,将读取到的文件用字节数组来存储,然后可以使用父类的 defineClass 来转换成字节码。

如果想破坏双亲委派的话,就重写 loadClass 方法, 否则不用重写

注意:

1.ClassLoader提供的 protected final Class<?> defineClass(String name, byte[] b, int off, int len) 是用来将字节数组转换成字节码文件的,传入参数 是 (类名,字节数组数据,字节数组读取的开始下标,字节数组的长度)

示例:读取某文件的下的某class文件

创建一个名为MyClassLoader的类加载器:

import java.io.*;

public class MyClassLoader extends ClassLoader{
    String path ;
    MyClassLoader(String dir){
        this.path = dir ;
    }

    @Override
    protected Class<?> findClass(String name) throws ClassNotFoundException {
        try {
            this.path = this.path + name +".class";
            File f = new File(path);
            InputStream in = new FileInputStream(f);
            byte [] bys = new byte[  (int)f.length() ];
            int len = 0;
            while( (len = in.read(bys) )!= -1  ){

            }
            // byte[] -> .class
            return defineClass(name,bys,0,bys.length);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return super.findClass(name);
    }
}

测试:

在如下目录,生成一个Hello.class字节码文件

Hello.java:

public class Hello {
    public void sayHello(){
        System.out.println("Hello World!");
    }
}

在这里插入图片描述

测试类:

import java.lang.reflect.Method;

public class Test {
    public static void main(String[] args) throws Exception {
        MyClassLoader my = new MyClassLoader("D:\\test\\JVMtest\\");
        Class<?> c1 = my.loadClass("Hello");
        Object o = c1.newInstance();
        Method d = c1.getMethod("sayHello",null);
        d.invoke(o);
    }
}

运行测试类:

在这里插入图片描述

类加载器的使用及自定义类加载器

package com.tech.load.def;
 

public class UserImpl {
    static {
        System.out.println("UserImpl init ...");
    }
}
package com.tech.load.def;
 

public class DefLoader {
    public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException {
        //上下文类加载器,默认使用的是 应用程序类加载器
//        ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader();
//        Class<?> c1 = contextClassLoader.loadClass("com.tech.load.def.UserImpl");
//        c1.newInstance(); //classloader.loadClass 不会触发初始化,当创建对象时执行初始化,执行静态程序块内容 输出 "UserImpl init ..."
//        ClassLoader contextClassLoader1 = Thread.currentThread().getContextClassLoader();
//        Class<?> c2 = contextClassLoader1.loadClass("com.tech.load.def.UserImpl");
//        c2.newInstance(); //使用相同的类加载器 加载相同的类名 则加载的是同一个类,c1 c2是同一个类,由于已经初始化过 创建对象不再初始化 不再打印  "UserImpl init ..."
//        System.out.println(contextClassLoader==contextClassLoader1); //true 获取的上下文类加载器是同一个类加载器 
//        System.out.println(c1==c2); // true 同一个类加载器器,加载同名的类,第一次加载时加载的类会缓存到类加载器的缓存,再次加载直接在缓存读取,两次加载的是同一个类
        
        //直接获取类的类加载器 应用程序类加载器
        ClassLoader classLoader = UserImpl.class.getClassLoader();
        ClassLoader classLoader1 = UserImpl.class.getClassLoader();
        System.out.println(classLoader==classLoader1); //true 获取的是同一个应用程序类加载器
       
        ClassLoader contextClassLoader = Thread.currentThread().getContextClassLoader();
        System.out.println(classLoader==contextClassLoader); //true 线程上下文类加载器默认采用的也是应用程序类加载器 与通过类型对象getClassLoader获取方式相同
 
        Class<?> c1 = Class.forName("com.tech.load.def.UserImpl"); //会触发类的初始化
        ClassLoader classLoader2 = c1.getClassLoader();
        System.out.println(classLoader==classLoader2); //true 获取的是同一个应用程序类加载器
        
    }
}

在应用程序中,默认我们获取上下文类加载器、类型对象getClassLoader都是采用的同一个应用程序类加载器,类在第一次被加载后会缓存到类加载器的缓存中,由于是同一个类加载器此时同名的类不能被多次加载,且应用程序类加载器只能加载classpath下的类。

如果我们想加载自定义路径下的类,需要用到自定义类加载器,可以去指定路径下加载类,且通过创建多个类加载器对象,加载的同名类相互隔离,也就是说同名类可以被多个自定义类加载器对象加载。

编写自定义类加载器:

  • 继承ClassLoader;
  • 重写findClass方法在指定路径下进行类的加载,得到字节数组,然后使用defineClass根据字节数组生成字节码文件 也就是class文件;

编写一个测试Goods放在D盘下,javac得到class文件

 

public class Goods {
    static {
        System.out.println("Goods init ...");
    }
}

javac Goods.java

package com.tech.load.def;
 
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.NIO.file.Files;
import java.nio.file.Paths;
 

public class DefLoad7 {
    public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException {
        MyClassLoader classLoader1 = new MyClassLoader();
        Class<?> c1 = classLoader1.loadClass("Goods");
        Class<?> c2 = classLoader1.loadClass("Goods");
        System.out.println(c1==c2);//true 使用同一个类加载器加载同名类两次,实际只加载了一次,第二次是在类加载器的缓存加载的 结果两次加载的是同一个
        c1.newInstance(); //会初始化
        c2.newInstance(); //不会初始化 
        
        MyClassLoader classLoader2 = new MyClassLoader();
        Class<?> c3 = classLoader2.loadClass("Goods");
        System.out.println(c1==c3); //false 使用不同的类加载器对同一个类进行加载,会得到不同的类型对象
        c3.newInstance(); //会初始化
    }
}
 
//自定义类加载器 加载D盘下的类
class MyClassLoader extends ClassLoader{
    
    //去指定的路径下加载类
    //name是类名称
    @Override
    protected Class<?> findClass(String name) throws ClassNotFoundException {
        String path="D:\\"+name+".class";
        try {
            ByteArrayOutputStream os = new ByteArrayOutputStream();
            //将指定路径下的文件 拷贝到输出流
            Files.copy(Paths.get(path),os);
            byte[] bytes = os.toByteArray();
            //调用父类的方法 根据字节数组生成字节码文件 也就是class文件
            //bytes -> *.class
 
            return defineClass(name,bytes,0,bytes.length);
        } catch (IOException e) {
            e.printStackTrace();
            throw new ClassNotFoundException("类文件未找到",e);
        }
    }
}

使用自定义加载器,创建多个类加载器对象去加载同一个类,会得到多个类型对象。 

以上为个人经验,希望能给大家一个参考,也希望大家多多支持编程网。

--结束END--

本文标题: Java中如何自定义一个类加载器

本文链接: https://www.lsjlt.com/news/173322.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • Java中如何自定义一个类加载器
    目录如何自定义加载器?示例:读取某文件的下的某class文件类加载器的使用及自定义类加载器如何自定义加载器? 1.创建一个自定义加载器类 继承 ClassLoader 类 2.重写 ...
    99+
    2022-11-21
    Java自定义类加载器 自定义类加载器 Java类加载器
  • 怎么在java中自定义一个类加载器
    本篇文章为大家展示了怎么在java中自定义一个类加载器,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。如果要使用自定义类加载器加载class文件,就需要继承java.lang.ClassLoader类...
    99+
    2023-05-30
    java
  • java类加载器怎么自定义
    要自定义Java类加载器,可以继承ClassLoader类,并重写它的findClass()方法。下面是一个简单的示例:```jav...
    99+
    2023-09-14
    java
  • java怎么自定义类加载器
    要自定义类加载器,可以按照以下步骤进行:1. 创建一个类,继承自java.lang.ClassLoader类,覆盖其中的findCl...
    99+
    2023-09-14
    java
  • java自定义类加载器如何实现类隔离
    目录自定义类加载器准备通过URLClassLoader来实现【推荐】通过继承ClassLoader实现网上java自定义类加载器很多容易找到,但是都是加载的单个类,如果被加载的类,有...
    99+
    2022-11-21
    java类隔离 自定义类加载器 java类加载器
  • Java基础之自定义类加载器
    目录一、类加载器关系二、基于本地class文件的自定义类加载器三、遇到的问题四、基于网络(url)class文件的自定义类加载器一、类加载器关系 自定义类加载器 创建一个类继承C...
    99+
    2022-11-12
  • 如何在Java中自定义一个枚举类
    本文章向大家介绍如何在Java中自定义一个枚举类的基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。Java的特点有哪些Java的特点有哪些1.Java语言作为静态面向对象编程语言的代表,实现了面向对象理论,允许程序...
    99+
    2023-06-06
  • Java通过自定义类加载器实现类隔离
    目录前言类隔离是什么使用场景解决方案重写findClass重写loadClass总结前言 由于微服务的快速迭代、持续集成等特性,越来越多的团队更倾向于它。但是也体现出了一些问题,比如...
    99+
    2022-11-13
    Java 类加载器 类隔离 Java 类加载器 Java 类隔离
  • Java自定义类加载器实现类隔离详解
    目录一、背景二、解决思路2.1 创建依赖所在目录2.2 定义操作接口2.3 编写并构建业务包2.4 自定义类加载器2.5 主流程步骤三、总结一、背景 某服务需要连接操作多种组件(每种...
    99+
    2023-03-02
    Java类加载器实现类隔离 Java类加载器 类隔离 Java类加载器 Java 类隔离
  • Java怎么自定义类加载器实现类隔离
    这篇“Java怎么自定义类加载器实现类隔离”文章的知识点大部分人都不太理解,所以小编给大家总结了以下内容,内容详细,步骤清晰,具有一定的借鉴价值,希望大家阅读完这篇文章能有所收获,下面我们一起来看看这篇“Java怎么自定义类加载器实现类隔离...
    99+
    2023-07-05
  • 如何在Java中自定义封装一个JDBC工具类
    如何在Java中自定义封装一个JDBC工具类?针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。步骤① 创建配置文件(config.properties),用于存放注册驱动和连接...
    99+
    2023-06-06
  • Java自定义类加载器及JVM自带的类加载器之间的交互关系是什么
    这篇“Java自定义类加载器及JVM自带的类加载器之间的交互关系是什么”文章,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们一定要参考一下,对于“Java自定义类加载器及JVM自带的类加载器之间的交互关系是什么”,小编整理...
    99+
    2023-06-06
  • 使用Java如何自定义一个迭代器
    使用Java如何自定义一个迭代器?针对这个问题,这篇文章详细介绍了相对应的分析和解答,希望可以帮助更多想解决这个问题的小伙伴找到更简单易行的方法。具体如下:编写自己的Iterator,实现Iterator接口,这里多说一句,实现Iterab...
    99+
    2023-05-31
    java 自定义 迭代器
  • Android如何自定义加载圈
    本篇内容介绍了“Android如何自定义加载圈”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!<RelativeLayout ...
    99+
    2023-07-02
  • Java如何自定义一个变长数组
    这篇文章主要介绍“Java如何自定义一个变长数组”的相关知识,小编通过实际案例向大家展示操作过程,操作方法简单快捷,实用性强,希望这篇“Java如何自定义一个变长数组”文章能帮助大家解决问题。思路分析主要功能点:新建时可以指定容量大小,不指...
    99+
    2023-07-04
  • java swing如何实现加载自定义的字体
    这篇文章主要介绍了java swing如何实现加载自定义的字体,具有一定借鉴价值,感兴趣的朋友可以参考下,希望大家阅读完这篇文章之后大有收获,下面让小编带着大家一起了解一下。java swing 加载自定义的字体在实际开发中, 我们需要把字...
    99+
    2023-06-25
  • 如何在Android应用中添加一个自定义弹框
    如何在Android应用中添加一个自定义弹框?很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。实现步骤:1.xml布局实现<&#63;xml vers...
    99+
    2023-05-31
    android roi
  • vue如何自定义加载指令
    本文小编为大家详细介绍“vue如何自定义加载指令”,内容详细,步骤清晰,细节处理妥当,希望这篇“vue如何自定义加载指令”文章能帮助大家解决疑惑,下面跟着小编的思路慢慢深入,一起来学习新知识吧。前言用过element-ui的都应该知道,里面...
    99+
    2023-07-02
  • uniapp如何全局自定义加载
    随着移动互联网的迅速发展,移动应用已经成为人们生活中不可或缺的一部分。而在移动应用开发中,加载动画就显得格外重要,它可以明显提升用户体验,让用户更快地感知到应用的反馈。而本文将介绍如何利用uniapp实现全局自定义加载动画,提升用户体验。一...
    99+
    2023-05-22
  • 利用SpringMVC如何实现一个自定义类型转换器
    这篇文章将为大家详细讲解有关利用SpringMVC如何实现一个自定义类型转换器,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。我们在使用SpringMVC时,常常需要把表单中的参数映射到我们对...
    99+
    2023-05-31
    springmvc 类型转换器
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作