从JAVA虚拟机的角度来说,只存在两种不一样的类加载器:一种是启动类加载器(Bootstrap ClassLoader),这个类加载器使用C++语言实现,是虚拟机自身的一部分;另外一种就是全部其余的类加载器,这些加载器都由Java语言实现,独立于虚拟机外部,而且全都继承自抽象类java,lang.ClassLoader。java
(1)启动类加载器:这个类加载器负责将存放在<JAVA_HOME>\lib 目录下的,例如rt.jar包。this
(2)扩展类加载器:这个类加载器由sun.misc.Launcher$ExtClassLoader实现。它负责加载<JAVA_HOME>\lib\ext 目录下的。或者被java.ext.dirs系统变量所指定的路径中的全部类库,开发者可用直接使用扩展类加载器。spa
(3)应用程序类加载器:这个类加载器由sun.misc.Launcher$AppClassLoader实现。因为这个类加载器是ClassLoader中的getSystemClassLoader()方法的返回值,全部通常也称它为系统类加载器。它负责加载用户路径(ClassPath)上所指定的类库,开发者可用直接使用这个类加载器,若是应用程序中没有自定义过本身的类加载器,通常状况下这个就是程序中默认的类加载器。code
(4)自定义类加载器:就是本身自定义的类加载器。blog
protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException { synchronized (getClassLoadingLock(name)) { // First, check if the class has already been loaded // 首先,检查请求的类是否已经被加载过 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) { // ClassNotFoundException thrown if class not found // 若是父类加载器抛出ClassNotFoundException // from the non-null parent class loader // 说明父类加载器没法完成加载请求 } if (c == null) { // If still not found, then invoke findClass in order // to find the class. // 在父类加载器没法加载的时候,再调用自己的findClass方法进行类加载 long t1 = System.nanoTime(); c = findClass(name); // this is the defining class loader; record the stats sun.misc.PerfCounter.getParentDelegationTime().addTime(t1 - t0); sun.misc.PerfCounter.getFindClassTime().addElapsedTimeFrom(t1); sun.misc.PerfCounter.getFindClasses().increment(); } } if (resolve) { resolveClass(c); } return c; } }
注意:即便自定义了本身的类加载器,强行用defineClass()方法区加载一个以"java.lang"开头的类也不会成功,若是尝试这样的话,将会收到一个由虚拟机本身抛出的"java.lang.ScurityException:Prohibitted package name:java.lang"异常。继承