Classloader
在理解了类的生命周期与加载过程之后,接下来就须要理解类加载器,即Classloader。
JVM 中内置了三个重要的 ClassLoader,除了 BootstrapClassLoader 其余类加载器全副继承自java.lang.ClassLoader
- BootstrapClassLoader(启动类加载器)
最顶层的加载类,由 C++实现,负责加载 %JAVA_HOME%/lib目录下的 jar 包和类或者被 -Xbootclasspath参数指定的门路中的所有类 - ExtensionClassLoader(扩大类加载器)
次要负责加载 %JRE_HOME%/lib/ext 目录下的 jar 包和类,或被 java.ext.dirs 零碎变量所指定的门路下的 jar 包。 - AppClassLoader(应用程序类加载器)
面向咱们用户的加载器,负责加载以后利用 classpath 下的所有 jar 包和类。
双亲委派模型
当一个类加载器收到类加载工作时,会先交给本人的父加载器去实现,因而最终加载工作都会传递到最顶层的BootstrapClassLoader,只有当父加载器无奈实现加载工作时,才会尝试本人来加载。然而相熟Java的人都晓得,Java中只有父类而没有母类的说法,顾双亲其实具备误导性,自己更违心了解为,父类委派模型,以下为官网阐明
- The Java platform uses a delegation model for loading classes. The basic idea is that every class loader has a “parent” class loader. When loading a class, a class loader first “delegates” the search for the class to its parent class loader before attempting to find the class itself.
Classloader 加载过程
protected Class<?> loadClass(String name, boolean resolve) throws ClassNotFoundException{ synchronized (getClassLoadingLock(name)) { // 首先查看这个类是否曾经被加载,在JVM生命周期中,一个类只会加载一次 Class<?> c = findLoadedClass(name); if (c == null) { long t0 = System.nanoTime(); try { if (parent != null) { // 如果父类加载器不为空,则应用父类加载器加载 c = parent.loadClass(name, false); } else { // 如果父类加载器为空,则应用顶层bootstrap加载器 c = findBootstrapClassOrNull(name); } } catch (ClassNotFoundException e) { // 如果以上加载失败,则持续往下执行 } if (c == null) { // 走完上述代码仍没有加载胜利,则尝试本人加载 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; }}
双亲委派模型的益处
- 保障了 Java 程序的稳固运行,能够防止类的反复加载,VM通过类名与加载器确定惟一的类
- 保障了 Java 外围 API 不被篡改,如果没有应用双亲委派模型,而是每个类加载器加载各自的类,就会呈现一些问题,比方开发者本人定义一个名为 java.lang.Object 类,程序运行时,零碎就会呈现多个不同的 Object 类。
如果不想用双亲委派模型
- 如果不想突破双亲委派模型,就重写 ClassLoader 类中的 findClass() 办法即可,无奈被父类加载器加载的类最终会通过这个办法被加载
- 如果想突破双亲委派模型则须要重写 loadClass() 办法
自定义类加载器
自定义加载器,须要继承 ClassLoader