seo优化或网站编辑,分析可口可乐网站建设的目的,百度网盘资源,wordpress博客系统安装教程类加载器
1 类加载器的分类
JVM 支持两种类型的类加载器#xff1a;引导类加载器#xff08;Bootstrap ClassLoader#xff09;和自定义类加载器#xff08;User-Defined ClassLoader#xff09;
从概念上来讲#xff0c;自定义类加载器一般指的是程序中由开发人员自定…类加载器
1 类加载器的分类
JVM 支持两种类型的类加载器引导类加载器Bootstrap ClassLoader和自定义类加载器User-Defined ClassLoader
从概念上来讲自定义类加载器一般指的是程序中由开发人员自定义的一类加载器但是 Java 虚拟机规范却没有这么定义而是将所有派生于抽象类 ClassLoader 的类加载器都划分为自定义类加载器
无论类加载器的类型如何划分在程序中我们最常见的类加载器始终只有 3 个如下所示 关于 ClassLoader: 测试代码ClassLoaderTest.java
public class ClassLoaderTest {public static void main(String[] args) {// 获取系统应用类加载器ClassLoader systemLoader ClassLoader.getSystemClassLoader();System.out.println(systemLoader); // sun.misc.Launcher$AppClassLoader18b4aac2// 获取 systemLoader 的上层扩展类加载器ClassLoader extClassLoader systemLoader.getParent();System.out.println(extClassLoader); // sun.misc.Launcher$ExtClassLoader4554617c// 试图获取 extClassLoader 的上层 Bootstrap ClassLoder获取不到引导类加载器ClassLoader bootstrapLoader extClassLoader.getParent();System.out.println(bootstrapLoader); // null// 用户自定义类的类加载器默认使用系统类加载器进行加载ClassLoader classLoader ClassLoaderTest.class.getClassLoader();System.out.println(classLoader); // sun.misc.Launcher$AppClassLoader18b4aac2// String 的类加载器也是引导类加载器 -- Java 的核心类库都是使用引导类加载器进行加载的ClassLoader classLoader2 String.class.getClassLoader();System.out.println(classLoader2); // null}
}2 虚拟机自带的加载器
2.1 启动类加载器引导类加载器Bootstrap ClassLoader
这个类加载器使用 C/C 语言实现的嵌套在 JVM 内部它用来加载 Java 的核心库JAVA_HOME/jre/lib/rt.jar、resources.jar 或 sun.boot.class.path 路径下的内容用于提供 JVM 自身需要的类并不继承自 java.lang.ClassLoader没有父加载器加载扩展类和应用程序类加载器并指定为它们的父类加载器出于安全考虑Bootstrap ClassLoader 启动类加载器只加载包名为 java、javax、sun 开头的类
测试类 ClassLoaderTest2.java
public class ClassLoaderTest2 {public static void main(String[] args) {System.out.println( 启动类加载器 );// 获取 BootstrapClassLoader 能够加载的 API 路径URL[] urLs Launcher.getBootstrapClassPath().getURLs();for (URL urL : urLs) {System.out.println(urL.toExternalForm());}// 验证 jsse.jar 包下 Provider 类的类加载器为 Bootstrap ClassLoaderSystem.out.println(Provider.class.getClassLoader()); // null}
}Provider 类由引导类加载器加载 输出结果
2.2 扩展类加载器Extension ClassLoader
Java 语言编写的由 sun.misc.Launcher$ExtClassLoader 实现派生于 ClassLoader 类父类加载器为启动类加载器从 java.ext.dirs 系统属性所指定的目录中加载类库或从 JDK 的安装目录的 jre/lib/ext 子目录扩展目录下加载类库。如果用户创建的 JAR 放在此目录下也会自动由扩展类加载器加载
测试类 ClassLoaderTest3.class
public class ClassLoaderTest3 {public static void main(String[] args) {System.out.println( 扩展类加载器 );String extDirs System.getProperty(java.ext.dirs);for (String path : extDirs.split(;)) {System.out.println(path);}// 验证 CurveDB 是由 ExtClassLoader 加载器所加载的System.out.println(CurveDB.class.getClassLoader()); // sun.misc.Launcher$ExtClassLoader7ea987ac}
}CurveDB 类是由 ExtClassLoader 加载器所加载的 输出结果
2.3 应用程序类加载器系统类加载器AppClassLoader
Java 语言编写由 sun.misc.Launcher$AppClassLoader 实现派生于 ClassLoader 类父类加载器为扩展类加载器它负责加载环境变量 classpath 或系统属性 java.class.path 指定路径下的类库应用程序类加载器程序中默认的类加载器一般来说Java 应用的类都是由它来完成加载通过 ClassLoader#getSystemClassLoader() 方法可以获取到该类加载器
测试类 ClassLoaderTest.java
public class ClassLoaderTest4 {public static void main(String[] args) {// 获取用户自定义类的类加载器System.out.println(ClassLoaderTest4.class.getClassLoader());/*** 输出结果为sun.misc.Launcher$AppClassLoader18b4aac2*/}
}3 用户自定义类加载器
在 Java 的日常应用程序开发中类的加载几乎都是同上述 3 种类加载器相互配合完成的但是在必要的时候我们也可以自定义类加载器来定制类的加载方式。
3.1 为什么要自定义类加载器
隔离加载类修改类加载的方式扩展加载源防止源码泄漏
3.2 自定义类加载器实现步骤
开发人员可以通过继承抽象类 java.lang.ClassLoader 类的方式实现自己的类加载器以满足一些特殊的需求在 JDK 1.2 之前自定义类加载器时总会去继承 ClassLoader 类并重写 loadClass() 方法从而实现自定义的加载器类但是在 JDK 1.2 之后已不再建议用户覆盖 loadClass() 方法而是建议把自定义类加载的逻辑写在 findClass() 方法中在编写自定义类加载器时如果没有太过于复杂的需求可以直接继承 URLClassLoader类这样就可以避免自己去编写 findClass() 方法及其获取字节码流的方式使自定义类加载器编写更加简洁
简单的类加载器实现 CustomClassLoader.java
public class CustomClassLoader extends ClassLoader {Overrideprotected Class? findClass(String name) throws ClassNotFoundException {try {byte[] result getClassFromCustomPath(name);if (result null) {throw new FileNotFoundException();} else {return defineClass(name, result, 0, result.length);}} catch (FileNotFoundException e) {e.printStackTrace();}throw new ClassNotFoundException(name);}private byte[] getClassFromCustomPath(String name) {// 从自定义路径中加载指定类细节略// 如果指定路径的字节码文件进行了加密则需要在此方法中进行解密操作return null;}public static void main(String[] args) {CustomClassLoader customClassLoader new CustomClassLoader();try {Class? clazz Class.forName(One, true, customClassLoader);Object obj clazz.newInstance();System.out.println(obj.getClass().getClassLoader());} catch (Exception e) {e.printStackTrace();}}
}4 关于 ClassLoader
ClassLoader 类是一个抽象类其后所有的类加载器都继承自 ClassLoader 不包括启动类加载器
4.1 方法介绍
方法名称描述getParent()返回该类加载器的超类加载器loadClass(String name)加载名称为 name 的类返回结果为 java.lang.Class 类的实例findClass(String name)查找名为 name 的类返回结果为 java.lang.Class 类的实例findLoadedClass(String name)查找名为 name 的已经被加载过的类返回结果为 java.lang.Class 的类的实例defineClass(String name, byte[] b, int off, int len)把字节数组 b 中的内容转换为一个 Java 类返回结果为 java.lang.Class 类的实例resolveClass(Class? c)连接指定的一个 Java 类
4.2 获取 ClassLoader 的途径
获取当前类的 ClassLoader: clazz.getClassLoader()获取当前线程上下文的 ClassLoader: Thread.currentThread().getContextClassLoader()获取系统的 ClassLoader: ClassLoader.getSystemClassLoader()获取调用都的 ClassLoader: DriverManager.getCallerClassLoader()