类加载器
类加载器的作用
类加载的作用:将class文件字节码内容加载到内存中,并将这些静态数据转换成方法区的运行时数据结构,然后在堆中生成一个代表这个类的java.lang.Class对象,作为方法区中类数据的访问入口。
类缓存∶标准的JavaSE类加载器可以按要求查找类,但一旦某个类被加载到类加载器中,它将维持加载(缓存)一段时间。不过JVM垃圾回收机制可以回收这些Class对象
类加载器作用是用来把类(class)装载进内存的。JVM规范定义了如下类型的类的加载器。
引导类加载器(bootstrap class loader):
它用来加载 Java 的核心库(jre/lib/rt.jar),是用原生C++代码来实现的,并不继承自java.lang.ClassLoader。
加载扩展类和应用程序类加载器,并指定他们的父类加载器,在java中获取不到。
扩展类加载器(extensions class loader):
它用来加载 Java 的扩展库(jre/ext/*.jar)。Java 虚拟机的实现会提供一个扩展库目录。该类加载器在此目录里面查找并加载 Java 类。
系统类加载器(system class loader):
它根据 Java 应用的类路径(CLASSPATH)来加载 Java 类。一般来说,Java 应用的类都是由它来完成加载的。可以通过 ClassLoader.getSystemClassLoader()来获取它。
自定义类加载器(custom class loader):
除了系统提供的类加载器以外,开发人员可以通过继承 java.lang.ClassLoader类的方式实现自己的类加载器,以满足一些特殊的需求。
package reflect;
public class Test06 {
public static void main(String[] args) throws ClassNotFoundException {
//获取系统类的加载器
ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader();
System.out.println(systemClassLoader);
//获取系统类加载器的父类加载器---->扩展类加载器
ClassLoader systemParentLoader = systemClassLoader.getParent();
System.out.println(systemParentLoader);
//获取扩展类加载器的父类加载器---->根加载器(C/C++)
ClassLoader parent = systemParentLoader.getParent();
System.out.println(parent);
//测试当前类是哪个加载器加载的
ClassLoader classLoader = Class.forName("reflect.Test06").getClassLoader();
System.out.println(classLoader);
//测试JDK内置的类是哪个加载器加载的
ClassLoader classLoader1 = Class.forName("reflect.Test06").getClassLoader();
System.out.println(classLoader1);
//如何获得系统类加载器可以加载的路径
System.out.println(System.getProperty("java.class.path"));
/*
C:\Program Files\Java\jdk1.8.0_261\jre\lib\charsets.jar;
C:\Program Files\Java\jdk1.8.0_261\jre\lib\deploy.jar;
C:\Program Files\Java\jdk1.8.0_261\jre\lib\ext\access-bridge-64.jar;
C:\Program Files\Java\jdk1.8.0_261\jre\lib\ext\cldrdata.jar;
C:\Program Files\Java\jdk1.8.0_261\jre\lib\ext\dnsns.jar;
C:\Program Files\Java\jdk1.8.0_261\jre\lib\ext\jaccess.jar;
C:\Program Files\Java\jdk1.8.0_261\jre\lib\ext\jfxrt.jar;
C:\Program Files\Java\jdk1.8.0_261\jre\lib\ext\localedata.jar;
C:\Program Files\Java\jdk1.8.0_261\jre\lib\ext\nashorn.jar;
C:\Program Files\Java\jdk1.8.0_261\jre\lib\ext\sunec.jar;
C:\Program Files\Java\jdk1.8.0_261\jre\lib\ext\sunjce_provider.jar;
C:\Program Files\Java\jdk1.8.0_261\jre\lib\ext\sunmscapi.jar;
C:\Program Files\Java\jdk1.8.0_261\jre\lib\ext\sunpkcs11.jar;
C:\Program Files\Java\jdk1.8.0_261\jre\lib\ext\zipfs.jar;
C:\Program Files\Java\jdk1.8.0_261\jre\lib\javaws.jar;
C:\Program Files\Java\jdk1.8.0_261\jre\lib\jce.jar;
C:\Program Files\Java\jdk1.8.0_261\jre\lib\jfr.jar;
C:\Program Files\Java\jdk1.8.0_261\jre\lib\jfxswt.jar;
C:\Program Files\Java\jdk1.8.0_261\jre\lib\jsse.jar;
C:\Program Files\Java\jdk1.8.0_261\jre\lib\management-agent.jar;
C:\Program Files\Java\jdk1.8.0_261\jre\lib\plugin.jar;
C:\Program Files\Java\jdk1.8.0_261\jre\lib\resources.jar;
C:\Program Files\Java\jdk1.8.0_261\jre\lib\rt.jar;
D:\onyx-antiplag-master\JavaAgain\out\production\JavaAgain;
C:\Users\Administrator\.m2\repository\org\jetbrains\annotations\19.0.0\annotations-19.0.0.jar;
D:\IntelliJ IDEA Community Edition 2020.2.3\lib\idea_rt.jar
*/
}
}
运行结果
sun.misc.Launcher$AppClassLoader@18b4aac2
sun.misc.Launcher$ExtClassLoader@74a14482
null
sun.misc.Launcher$AppClassLoader@18b4aac2
sun.misc.Launcher$AppClassLoader@18b4aac2
C:\Program Files\Java\jdk1.8.0_261\jre\lib\charsets.jar;C:\Program Files\Java\jdk1.8.0_261\jre\lib\deploy.jar;C:\Program Files\Java\jdk1.8.0_261\jre\lib\ext\access-bridge-64.jar;C:\Program Files\Java\jdk1.8.0_261\jre\lib\ext\cldrdata.jar;C:\Program Files\Java\jdk1.8.0_261\jre\lib\ext\dnsns.jar;C:\Program Files\Java\jdk1.8.0_261\jre\lib\ext\jaccess.jar;C:\Program Files\Java\jdk1.8.0_261\jre\lib\ext\jfxrt.jar;C:\Program Files\Java\jdk1.8.0_261\jre\lib\ext\localedata.jar;C:\Program Files\Java\jdk1.8.0_261\jre\lib\ext\nashorn.jar;C:\Program Files\Java\jdk1.8.0_261\jre\lib\ext\sunec.jar;C:\Program Files\Java\jdk1.8.0_261\jre\lib\ext\sunjce_provider.jar;C:\Program Files\Java\jdk1.8.0_261\jre\lib\ext\sunmscapi.jar;C:\Program Files\Java\jdk1.8.0_261\jre\lib\ext\sunpkcs11.jar;C:\Program Files\Java\jdk1.8.0_261\jre\lib\ext\zipfs.jar;C:\Program Files\Java\jdk1.8.0_261\jre\lib\javaws.jar;C:\Program Files\Java\jdk1.8.0_261\jre\lib\jce.jar;C:\Program Files\Java\jdk1.8.0_261\jre\lib\jfr.jar;C:\Program Files\Java\jdk1.8.0_261\jre\lib\jfxswt.jar;C:\Program Files\Java\jdk1.8.0_261\jre\lib\jsse.jar;C:\Program Files\Java\jdk1.8.0_261\jre\lib\management-agent.jar;C:\Program Files\Java\jdk1.8.0_261\jre\lib\plugin.jar;C:\Program Files\Java\jdk1.8.0_261\jre\lib\resources.jar;C:\Program Files\Java\jdk1.8.0_261\jre\lib\rt.jar;D:\onyx-antiplag-master\JavaAgain\out\production\JavaAgain;C:\Users\Administrator\.m2\repository\org\jetbrains\annotations\19.0.0\annotations-19.0.0.jar;D:\IntelliJ IDEA Community Edition 2020.2.3\lib\idea_rt.jar
双亲委派机制
某个特定的类加载器在接到加载类的请求时,首先将加载任务委托交给父类加载器,父类加载器又将加载任务向上委托,直到最父类加载器,如果最父类加载器可以完成类加载任务,就成功返回,如果不行就向下传递委托任务,由其子类加载器进行加载。
双亲委派机制的好处:
保证java核心库的安全性(例如:如果用户自己写了一个java.lang.String类就会因为双亲委派机制不能被加载,不会破坏原生的String类的加载)
代理模式
与双亲委派机制相反,代理模式是先自己尝试加载,如果无法加载则向上传递。tomcat就是代理模式。