程序员Java 杂谈

Java如何自定义类加载器

2018-09-14  本文已影响0人  打铁大师

类加载器的详细描述

我们可以编写自己的用于特殊目的的类加载器,这使得我们可以在向虚拟机传递字节码之前执行定制的检查。

如何自定义类加载器

如果想要编写自己的类加载器,只需要两步:

ClassLoader超类的loadClass方法用于将类的加载操作委托给其父类加载器去进行,只有当该类尚未加载并且父类加载器也无法加载该类时,才调用findClass方法。
如果要实现该方法,必须做到以下几点:

1.为来自本地文件系统或者其他来源的类加载其字节码。
2.调用ClassLoader超类的defineClass方法,向虚拟机提供字节码。

下面是自定义类加载器的一种实现方式:

public class CustomClassLoader extends ClassLoader {
    protected Class<?> findClass(String name) throws ClassNotFoundException {
      try {
          String cname = "/Users/wuzhenyu/Desktop/spring-boot/src/main/java/" + name.replace('.', '/') + ".class";
          byte[] classBytes = Files.readAllBytes(Paths.get(cname));
          Class<?> cl = defineClass(name, classBytes, 0, classBytes.length);
          if (cl == null) {
              throw new ClassNotFoundException(name);
          }
          return cl;
      } catch (IOException e) {
          System.out.print(e);
          throw new ClassNotFoundException(name);
      }
    }
}

我在该类的目录下准备了一个编译好的类文件SayHello.class(后缀改为了text),SayHello.class对应的Java代码如下:

public class SayHello {
   public static void main(String[] args) {
       System.out.print("Hello World");
   }
}

下面是测试类的代码:

测试前请删除SayHello.java文件

public class ClassLoaderTest {
    public static void main(String[] args) {
        try {
            ClassLoader loader = new CustomClassLoader();
            //调用loadClass加载sample.loader.SayHello类
            //无法加载到该类,因此会调用findClass方法
            Class<?> c = loader.loadClass("sample.loader.SayHello");
            Method m = c.getMethod("main", String[].class);
            m.invoke(null, (Object) new String[]{});
        } catch (Throwable e) {
            System.out.println(e);
        }
    }
}

运行结果如下:

Hello World

这是一个简单的实现自己类加载器的例子。在更复杂的案例中,使用的往往是加密过的类文件,加载该类字节码时,还需要解密。不然它们就不能由标准虚拟机来执行,也不能轻易被反汇编。

类加载器相关的API

1. java.lang.Class

2.java.lang.ClassLoader

3.java.net.URLClassLoader

4.java.lang.Thread

参考文献《Java 核心技术 卷二》

上一篇下一篇

猜你喜欢

热点阅读