Java小强个人技术博客站点    手机版
当前位置: 首页 >> Java >> Java自定义类的加载器

Java自定义类的加载器

5780 Java | 2022-2-14

Java程序在运行的时候,JVM通过类加载机制(ClassLoader)把class文件加载到内存中,只有class文件被载入内存,才能被其他class引用,使程序正确运行起来.


Java中的ClassLoader有三种:Bootstrap ClassLoader 、Extension ClassLoader、App ClassLoader。

1. Bootstrap ClassLoader

由C++写的,由JVM启动.

启动类加载器,负责加载java基础类,对应的文件是%JRE_HOME/lib/ 目录下的rt.jar、resources.jar、charsets.jar和class等

2.Extension ClassLoader

Java类,继承自URLClassLoader 扩展类加载器,

对应的文件是 %JRE_HOME/lib/ext 目录下的jar和class等

3.App ClassLoader

Java类,继承自URLClassLoader 系统类加载器,

对应的文件是应用程序classpath目录下的所有jar和class等


Java的加载机制是双亲委派机制来加载类

为什么要使用这种方式?这个是为了保证 如果加载的类是一个系统类,那么会优先由Bootstrap ClassLoader 、Extension ClassLoader先去加载,而不是使用我们自定义的ClassLoader去加载,保证系统的安全!


系统的ClassLoader只会加载指定目录下的class文件,如果你想加载自己的class文件,那么就可以自定义一个ClassLoader。

新建一个类继承自java.lang.ClassLoader,重写它的findClass方法,然后将class字节码数组转换为Class类的实例,调用loadClass方法即可。


新建一个样品Java文件,并生成class,然后拷贝到指定目录

package com.javacui.test;

public class ClassLoaderTest {
    public static void main(String[] args) {
        System.out.println("I am ClassLoaderTest");
        for (String str : args){
            System.out.println("参数:" + str);
        }
    }
}


自定义一个类加载器,加载该class文件并调用main方法

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.lang.reflect.Method;

public class MyClassLoader extends ClassLoader {
    public static void main(String[] args) throws Exception {
        //这个类class的路径
        String classPath = "D://temp/ClassLoaderTest.class";
        //类的全称,有包名的加包名
        String packageNamePath = "com.javacui.test.ClassLoaderTest";

        MyClassLoader myClassLoader = new MyClassLoader(classPath);
        //加载ClassLoaderTest类的class文件
        Class<?> myclass = myClassLoader.loadClass(packageNamePath);
        System.out.println("类加载器是:" + myclass.getClassLoader());
        //利用反射获取main方法
        Method method = myclass.getDeclaredMethod("main", String[].class);
        Object object = myclass.newInstance();
        String[] arg = {"java小强", "博客"};
        method.invoke(object, (Object) arg);
    }

    //指定路径
    private String path;

    public MyClassLoader(String classPath) {
        path = classPath;
    }

    /**
     * 重写findClass方法
     *
     * @param name 是我们这个类的全路径
     * @throws ClassNotFoundException
     */
    @Override
    protected Class<?> findClass(String name) throws ClassNotFoundException {
        Class myclass = null;
        // 获取该class文件字节码数组
        byte[] classData = getData();
        if (classData != null) {
            // 将class的字节码数组转换成Class类的实例
            myclass = defineClass(name, classData, 0, classData.length);
        }
        return myclass;
    }

    /**
     * 将class文件转化为字节码数组
     */
    private byte[] getData() {
        File file = new File(path);
        if (file.exists()) {
            FileInputStream in = null;
            ByteArrayOutputStream out = null;
            try {
                in = new FileInputStream(file);
                out = new ByteArrayOutputStream();
                byte[] buffer = new byte[1024];
                int size = 0;
                while ((size = in.read(buffer)) != -1) {
                    out.write(buffer, 0, size);
                }
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                try {
                    in.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
            return out.toByteArray();
        } else {
            return null;
        }
    }
}


输出

类加载器是:sun.misc.Launcher$AppClassLoader@14dad5dc
I am ClassLoaderTest
参数:java小强
参数:博客


如果想要保护你的class文件,那可以借助自定义类加载器,因为java的class文件是可以被轻易反编译的。

例如上面,我们生成class文件后,可以通过对称加密等方式进行加密,那么拿到的class字节都是加密后,是无法使用的,在上面的getData()方法中我们读取到了文件字节流,可以把该字节流再进行解密。


DES加密使用入门 http://www.javacui.com/java/17.html 

JAVA加密算法实现用例 密钥一致协议 http://www.javacui.com/Theory/273.html 

JAVA加密算法实现用例 数字签名 http://www.javacui.com/java/312.html 


推荐您阅读更多有关于“ extension Bootstrap 类加载器 ClassLoader URLClassLoader ”的文章

上一篇:Nacos单机模式集成MySQL 下一篇:静态代码块、构造代码块、构造方法的执行顺序

猜你喜欢

发表评论: