java应用环境中不一样的class分别由不一样的ClassLoader负责加载。
一个jvm中默认的classloader有Bootstrap ClassLoader、Extension ClassLoader、App ClassLoader,分别各司其职:java
其中Bootstrap ClassLoader是JVM级别的,由C++撰写;Extension ClassLoader、App ClassLoader都是java类,都继承自URLClassLoader超类。
Bootstrap ClassLoader由JVM启动,而后初始化sun.misc.Launcher ,sun.misc.Launcher初始化Extension ClassLoader、App ClassLoader。数组
类加载器的双亲委派加载机制(重点):当一个类收到了类加载请求,他首先不会尝试本身去加载这个类,而是把这个请求委派给父类去完成,每个层次类加载器都是如此,所以全部的加载请求都应该传送到启动类加载其中,只有当父类加载器反馈本身没法完成这个请求的时候(在它的加载路径下没有找到所需加载的Class),子类加载器才会尝试本身去加载。app
Bootstrap ClassLoader、Extension ClassLoader、App ClassLoader三者的关系以下:jvm
Bootstrap ClassLoader是Extension ClassLoader的parent,Extension ClassLoader是App ClassLoader的parent。url
可是这并非继承关系,只是语义上的定义,基本上,每个ClassLoader实现,都有一个Parent ClassLoader。spa
能够经过ClassLoader的getParent方法获得当前ClassLoader的parent。Bootstrap ClassLoader比较特殊,由于它不是java class因此Extension ClassLoader的getParent方法返回的是NULL。.net
了解了ClassLoader的原理和流程之后,咱们能够试试自定义ClassLoader。code
关于自定义ClassLoader:server
因为一些特殊的需求,咱们可能须要定制ClassLoader的加载行为,这时候就须要自定义ClassLoader了.blog
自定义ClassLoader须要继承ClassLoader抽象类,重写findClass方法,这个方法定义了ClassLoader查找class的方式。
主要能够扩展的方法有:
findClass 定义查找Class的方式
defineClass 将类文件字节码加载为jvm中的class
findResource 定义查找资源的方式
若是嫌麻烦的话,咱们能够直接使用或继承已有的ClassLoader实现,好比
java.net.URLClassLoader
java.security.SecureClassLoader
java.rmi.server.RMIClassLoader
sun.applet.AppletClassLoader
Extension ClassLoader 和 App ClassLoader都是java.net.URLClassLoader的子类。
这个是URLClassLoader的构造方法:
public URLClassLoader(URL[] urls, ClassLoader parent)
public URLClassLoader(URL[] urls)
urls参数是须要加载的ClassPath url数组,能够指定parent ClassLoader,不指定的话默认以当前调用类的ClassLoader为parent。
代码示例:
ClassLoader classLoader = new URLClassLoader(urls); Thread.currentThread().setContextClassLoader(classLoader); Class clazz=classLoader.loadClass("com.company.MyClass");//使用loadClass方法加载class,这个class是在urls参数指定的classpath下边。 Method taskMethod = clazz.getMethod("doTask", String.class, String.class);//而后咱们就能够用反射作些事情了 taskMethod.invoke(clazz.newInstance(),"hello","world");
因为classloader 加载类用的是全盘负责委托机制。所谓全盘负责,便是当一个classloader加载一个Class的时候,这个Class所依赖的和引用的全部 Class也由这个classloader负责载入,除非是显式的使用另一个classloader载入。
因此,当咱们自定义的classloader加载成功了com.company.MyClass之后,MyClass里全部依赖的class都由这个classLoader来加载完成。
自定义ClassLoader在某些应用场景仍是比较适用,特别是须要灵活地动态加载class的时候。