首页 > 编程语言 >Java自定义类加载器

Java自定义类加载器

时间:2022-11-21 22:44:52浏览次数:34  
标签:Java String 自定义 name return 加载 Class cls

通过继承java.lang.ClassLoader可以自定义类加载器。

步骤:

1、继承ClassLoader。

2、读取字节文件到字节数组中。

3、使用defineClass(类名,字节数组,off,length):将字节数组转换为类的Class的实例。 


 

 

准备工作:一个待加载的Hello.class,它的内容为一个main方法,控制台输出一句“hello world!”

通过继承java.lang.ClassLoader可以自定义类加载器。

准备:一个待加载的Hello.class,它的内容为一个main方法,控制台输出一句“hello world!”



 

创建自己的类加载器:

import java.io.*;

public class LrjClassLoader extends ClassLoader{
    private String rootDir;

    /**
     * 构造器:指定类加载的位置
     */
    public LrjClassLoader(String rootDir) {
        this.rootDir = rootDir;
    }

    /**
     * 查找名称为name的类,并且加载它,返回Class对象,
     * @param name
     * @return
     * @throws ClassNotFoundException
     */
    @Override
    protected Class<?> findClass(String name) throws ClassNotFoundException {
        Class<?> cls = findLoadedClass(name);

        if(cls!=null){
            return cls;//此类已经被加载过了
        }else {
            ClassLoader parent = this.getParent();
            try {
                cls = parent.loadClass(name);//让父类先加载
            }catch (Exception e){
                System.out.println("父类加载失败....准备自己淦!");
            }
            if(cls!=null){
                return cls;//感谢父类
            }else {
                //mmp,我自己加载
                byte[] classData = getClassDate(name);
                if(classData==null){
                    throw new ClassNotFoundException();//加载失败
                }else {
                    //将字节数组转换为类别 Class的实例。
                    cls = defineClass(name,classData,0,classData.length);
                    return cls;
                }
            }
        }
    }

    /**
     *把类的名字给我,我把它的字节码文件放在字节数组中给你。
     * @param name  类名
     * @return  字节数组:内容为它的class文件
     */
    private byte[] getClassDate(String name){
        String path = rootDir+"/"+name.replace('.','/')+".class";

        try(FileInputStream is = new FileInputStream(path);) {
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            byte[] buffer = new byte[1024];
            int len=0;
            while ((len=is.read(buffer))!=-1){
                baos.write(buffer,0,len);
            }
            baos.flush();
            //
            return baos.toByteArray();
        }catch (Exception e){
            e.printStackTrace();
        }
        return null;
    }
}
使用自定义的类加载器:

public class TestClassloader {
    public static void main(String[] args) throws Exception {
        //创建的时候指定加载空间
        LrjClassLoader lc = new LrjClassLoader("d:/my_file");
        //加载此类,获取Class对象
        Class aClass= lc.findClass("lurenjia.test.Hello");

        //运行Hello
        aClass.getMethod("main",String[].class).invoke(null,(Object)new String[]{});
    }
}
运行结果:
查看Hello.java

创建自己的类加载器:

import java.io.*;

public class LrjClassLoader extends ClassLoader{
    private String rootDir;

    /**
     * 构造器:指定类加载的加载位置
     */
    public LrjClassLoader(String rootDir) {
        this.rootDir = rootDir;
    }

    /**
     * 查找名称为name的类,并且加载它,返回Class对象,
     * @param name
     * @return
     * @throws ClassNotFoundException
     */
    @Override
    protected Class<?> findClass(String name) throws ClassNotFoundException {
        Class<?> cls = findLoadedClass(name);

        if(cls!=null){
            return cls;//此类已经被加载过了
        }else {
            ClassLoader parent = this.getParent();
            try {
                cls = parent.loadClass(name);//让父类先加载
            }catch (Exception e){
                System.out.println("父类加载失败....准备自己淦!");
            }
            if(cls!=null){
                return cls;//感谢父类
            }else {
                //mmp,我自己加载
                byte[] classData = getClassDate(name);
                if(classData==null){
                    throw new ClassNotFoundException();//加载失败
                }else {
                    //将字节数组转换为类的 Class的实例。
                    cls = defineClass(name,classData,0,classData.length);
                    return cls;
                }
            }
        }
    }

    /**
     *把类的名字给我,我把它的字节码文件放在字节数组中给你。
     * @param name  类名
     * @return  字节数组:内容为它的class文件
     */
    private byte[] getClassDate(String name){
        String path = rootDir+"/"+name.replace('.','/')+".class";

        try(FileInputStream is = new FileInputStream(path);) {
            ByteArrayOutputStream baos = new ByteArrayOutputStream();
            byte[] buffer = new byte[1024];
            int len=0;
            while ((len=is.read(buffer))!=-1){
                baos.write(buffer,0,len);
            }
            baos.flush();
            //
            return baos.toByteArray();
        }catch (Exception e){
            e.printStackTrace();
        }
        return null;
    }
}

 

使用自定义的类加载器:

public class TestClassloader {
    public static void main(String[] args) throws Exception {
        //创建的时候指定加载空间
        LrjClassLoader lc = new LrjClassLoader("d:/my_file");
        //加载此类,获取Class对象
        Class aClass= lc.findClass("lurenjia.test.Hello");

        //运行Hello
        aClass.getMethod("main",String[].class).invoke(null,(Object)new String[]{});
    }
}

 

运行结果:

标签:Java,String,自定义,name,return,加载,Class,cls
From: https://www.cnblogs.com/lurenjia-bky/p/16913669.html

相关文章

  • Java开发学习(四十二)----MyBatisPlus查询语句之条件查询
    一、条件查询的类MyBatisPlus将书写复杂的SQL查询条件进行了封装,使用编程的形式完成查询条件的组合。这个我们在前面都有见过,比如查询所有和分页查询的时候,都有看到......
  • java期末
    java知识1.Javac.exejava.exejavap.exejavadoc.exe的含义和用法;JavacA.javajavaAJavap?Javadoc?javac.exe是编译程序,用于编译.java文件java.exe是执行程序,......
  • idea使用oracle数据库报错《java.sql.SQLRecoverableException: IO 错误: Undefined E
    错误描述java.lang.RuntimeException:java.sql.SQLRecoverableException:IO错误:UndefinedError atcom.baomidou.mybatisplus.generator.config.DataSourceConfig.......
  • Java配置jdk环境变量
     配置:1、进入系统环境变量设置。  2、点击环境变量 3、如图所示:  4、如图所示:   5、点击确定退出配置界面检验:1、win+r,输入cmd,点击确定。 ......
  • jenkins配置从节点后运行报错java.net.ConnectException: Connection timed out: conn
    修改jenkins配置中的ip系统管理-系统配置  修改ip与访问地址相同 ......
  • QQ环境下分享自定义内容
     QQ环境下分享自定义内容:在head里加以下标签即可:<metaname="description"itemprop="description"content="竞猜让我智币分离"><metaitemprop="name"content="我是一个......
  • Java方法基础学习
    方法Java方法是语句的集合,它们在一起执行一个功能方法是解决一类问题的步骤的有序组合方法包含于类或对象中方法在程序中被创建,在其他地方被引用设计方法的原则:原......
  • 基于Swing+Java的影院购票系统,GUI界面
    基于Swing+Java的影院购票系统基于Swing+Java的电影院院购票系统基于Swing+Java的影院售票管理系统基于Swing+Java的电影院管理系统系统功能截图1.登录2.忘记密码......
  • Java命名规范
    命名规范  一、一般概念        1、尽量使用完整的英文描述符        2、采用适用于相关领域的术语        3、采用大小写混合使名字可读  ......
  • java学前基础
    java基础一.java注释1.单行注释:////这是单行注释2.多行注释:/*注释内容*//*这是多行注释这是多行注释*/3.文档注释(JavaDoc):/**注释内容*//***@......