在java中,ClassLoader负责把一个java类加载进Java虚拟机。为了防止重复加载和安全性方便的考虑,ClassLoader是具备层次结构的。java
ClassLoader的主要方法包括:git
protected final Class<?> defineClass(String name, byte[] b, int off, int len) throws ClassFormatError { return defineClass(name, b, off, len, null); }
经过defineClass是将byte数组转换为JVM可以识别的对象,能够看出,字节数组能够来自本地,网络等途径web
protected final Class<?> findLoadedClass(String name) { if (!checkName(name)) return null; return findLoadedClass0(name); }
经过类的全名来加载一个类数组
protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException { synchronized (getClassLoadingLock(name)) { // 首先检查class是否已经加载 Class c = findLoadedClass(name); if (c == null) { long t0 = System.nanoTime(); try { if (parent != null) { c = parent.loadClass(name, false); } else { c = findBootstrapClassOrNull(name); } } catch (ClassNotFoundException e) { // 当父classLoader没有加载的成功的时候抛出异常 } if (c == null) { // 若是还还加载成功,试图调用findClass来加载类 long t1 = System.nanoTime(); c = findClass(name); // 记录状态 sun.misc.PerfCounter.getParentDelegationTime().addTime(t1 - t0); sun.misc.PerfCounter.getFindClassTime().addElapsedTimeFrom(t1); sun.misc.PerfCounter.getFindClasses().increment(); } } if (resolve) { resolveClass(c); } return c; } }
能够看出,加载类的时候都是先从父类中加载安全
protected Class<?> findClass(String name) throws ClassNotFoundException { throw new ClassNotFoundException(name); }
findClass默认是没有任何实现的,只是抛出异常,所以咱们能够覆盖该方法, 重写咱们本身的类加载途径java-web
代码例子:怎么使用classLoader加载自定义byte数组并经过反射调用其中方法网络
https://git.oschina.net/null_584_3382/java-web-example/tree/masterspa
从文章前面的描述中,能够看出 class loader在加载类的时候,优先是从其父加载器中加载,而且每一个Class Loader 都有一个字段指向其父加载器(若是没有指定默认为AppClassLoader).net
ClassLoader的层次结构:code
上面的图是随便找的,下面简单介绍一下
这个类是为JVM本身服务的,加载JVM自身工做所须要的类,这个类彻底是由JVM本身控制的。该类其实并不遵照前面所规定的等级加载制度。这个类即没有父加载器,也没有子加载器。
这个加载器主要用于加载 java.ext.dirs目录下的类,也算是一种特殊的类加载器,他是往上能追溯到的最高加载器
这个类就是专门为咱们使用的,他的父加载器ExtClassLoader ,全部在ClassPath下的类都由他加载(前提你没有定义其余本身的ClassLoader)。咱们本身实现的ClassLoader的父加载器就是这个类。
ExtClassLoader 和AppClassLoader都是Launch的内部类,都继承URLClassLoader,而URLClassLoader又继承ClassLoader。
第一种方式是隐式加载方式,加载一个类的时候,若是他的父类没有加载,就会先加载其父类(顺带说一句,本身实现ClassLoader 的时候,也要准守先从父加载器中加载,否则加载到Java.xxx 的类的时候,就会提示报错,由于 java.xxx 的类是不容许从其余地方加载的)
第二种方式是显示加载,也就是咱们本身显示使用loadClass方法加载
// TODO