[JavaKeeper]JVM类加载子系统解毒( 三 )


它用来加载Java的核心库(JAVA_HOME/jre/lib/rt.jar、resource.jar或sun.boot.class.path路径下的内容) , 用于提供JVM自身需要的类
并不继承自java.lang.ClassLoader , 没有父加载器
加载扩展类和应用程序类加载器 , 并指定为他们的父类加载器
出于安全考虑 , Boostrap启动类加载器只加载名为java、Javax、sun等开头的类扩展类加载器(ExtensionClassLoader)
java语言编写 , 由sun.misc.Launcher$ExtClassLoader实现
派生于ClassLoader
父类加载器为启动类加载器
从java.ext.dirs系统属性所指定的目录中加载类库 , 或从JDK的安装目录的jre/lib/ext子目录(扩展目录)下加载类库 。 如果用户创建的JAR放在此目录下 , 也会自动由扩展类加载器加载应用程序类加载器(也叫系统类加载器 , AppClassLoader)
java语言编写 , 由sun.misc.Lanucher$AppClassLoader实现
派生于ClassLoader
父类加载器为扩展类加载器
它负责加载环境变量classpath或系统属性java.class.path指定路径下的类库
该类加载是程序中默认的类加载器 , 一般来说 , Java应用的类都是由它来完成加载的
通过ClassLoader#getSystemClassLoader()方法可以获取到该类加载器publicclassClassLoaderTest{publicstaticvoidmain(String[]args){//获取系统类加载器ClassLoadersystemClassLoader=ClassLoader.getSystemClassLoader();System.out.println(systemClassLoader);//sun.misc.Launcher$AppClassLoader@135fbaa4//获取其上层:扩展类加载器ClassLoaderextClassLoader=systemClassLoader.getParent();System.out.println(extClassLoader);//sun.misc.Launcher$ExtClassLoader@2503dbd3//再获取其上层:获取不到引导类加载器ClassLoaderbootstrapClassLoader=extClassLoader.getParent();System.out.println(bootstrapClassLoader);//null//对于用户自定义类来说 , 默认使用系统类加载器进行加载 , 输出和systemClassLoader一样ClassLoaderclassLoader=ClassLoaderTest.class.getClassLoader();System.out.println(classLoader);//sun.misc.Launcher$AppClassLoader@135fbaa4//String类使用引导类加载器进行加载 。 Java的核心类库都使用引导类加载器进行加载 , 所以也获取不到ClassLoaderclassLoader1=String.class.getClassLoader();System.out.println(classLoader1);//null//获取BootstrapClassLoader可以加载的api的路径URL[]urls=sun.misc.Launcher.getBootstrapClassPath().getURLs();for(URLurl:urls){System.out.println(url.toExternalForm());}}}用户自定义类加载器
在Java的日常应用程序开发中 , 类的加载几乎是由3种类加载器相互配合执行的 , 在必要时 , 我们还可以自定义类加载器 , 来定制类的加载方式为什么要自定义类加载器?
隔离加载类
修改类加载的方式
扩展加载源(可以从数据库、云端等指定来源加载类)
防止源码泄露(Java代码容易被反编译 , 如果加密后 , 自定义加载器加载类的时候就可以先解密 , 再加载)用户自定义加载器实现步骤
开发人员可以通过继承抽象类java.lang.ClassLoader类的方式 , 实现自己的类加载器 , 以满足一些特殊的需求
在JDK1.2之前 , 在自定义类加载器时 , 总会去继承ClassLoader类并重写loadClass()方法 , 从而实现自定义的类加载类 , 但是JDK1.2之后已经不建议用户去覆盖loadClass()方式 , 而是建议把自定义的类加载逻辑写在findClass()方法中
编写自定义类加载器时 , 如果没有太过于复杂的需求 , 可以直接继承URLClassLoader类 , 这样就可以避免自己去编写findClass()方法及其获取字节码流的方式 , 使自定义类加载器编写更加简洁ClassLoader常用方法