手写一个ClassLoader类加载器

Posted 醉酒的小男人

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了手写一个ClassLoader类加载器相关的知识,希望对你有一定的参考价值。

既然JVM已经提供了默认的类加载器,为什么还要定义自已的类加载器呢?因为Java中提供的默认ClassLoader,只加载指定目录下的jar和class,如果我们想加载其它位置的类或jar时,比如:我要加载网络上的一个class文件,通过动态加载到内存之后,要调用这个类中的方法实现我的业务逻辑。在这样的情况下,默认的ClassLoader就不能满足我们的需求了,所以需要定义自己的ClassLoader。

定义自已的类加载器分为两步:

1、继承java.lang.ClassLoader

2、重写父类的findClass方法

可能在这里有疑问,父类有那么多方法,为什么偏偏只重写findClass方法?因为JDK已经在loadClass方法中帮我们实现了ClassLoader搜索类的算法,当在loadClass方法中搜索不到类时,loadClass方法就会调用findClass方法来搜索类,所以我们只需重写该方法即可。如没有特殊的要求,一般不建议重写loadClass搜索类的算法。

第一步:建一个Person类:

public class Person {
    static {
        System.out.println("hello world");
    }
}

  找到Person的目录的上一层使用javac Person.java编译成Person.class文件:

 

第二步:手写类加载器:

import java.io.*;

//继承ClassLoader类,重写findclass方法
public class MyClassloader extends ClassLoader {

    private String path;
    private String classloaderName;

    public MyClassloader(String path, String classloaderName) {
        this.path = path;
        this.classloaderName = classloaderName;
    }

    //寻找类文件
    @Override
    protected Class<?> findClass(String name) throws ClassNotFoundException {
        byte[] b = loadClassData(name);
        return defineClass(name,b,0,b.length);
    }

    public byte[] loadClassData(String name){
       name = path + name +".class";
        InputStream in = null;
        ByteArrayOutputStream out = null;
        try {
            in = new FileInputStream(new File(name));
            out = new ByteArrayOutputStream();
            int i = 0;
            while ((i = in.read()) != -1){
               out.write(i);
            }
        }catch (Exception e){
            e.printStackTrace();
        }finally {
            try {
                out.close();
                in.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        return out.toByteArray();
    }

    public static void main(String[] args) {
        try {
            MyClassloader myClassloader = new MyClassloader("F:/workspace/mystudydemo/src/main/java/","myclassloader");
            Class c = myClassloader.findClass("Person");
            System.out.println(c.getClassLoader());
            System.out.println(c.getClassLoader().getParent());
            System.out.println(c.getClassLoader().getParent().getParent());
            c.newInstance();
        }catch (Exception e){
            e.printStackTrace();
        }
    }

}

 执行结果:

以上是关于手写一个ClassLoader类加载器的主要内容,如果未能解决你的问题,请参考以下文章

手写一个类加载器demo

jvm之java类加载机制和类加载器(ClassLoader)的详解

类加载器ClassLoader的理解

关于类加载器(ClassLoader)

Java类加载器(ClassLoader)

[Java安全]类加载器ClassLoader