当前位置: 首页 > 后端技术 > Java

ClassloaderClassloader&双亲委派模型

时间:2023-04-01 13:44:59 Java

Classloader了解了一个类的生命周期和加载过程之后,接下来就是了解类加载器,即Classloader。JVM内置了三个重要的类加载器。除BootstrapClassLoader外,其他类加载器均继承于java.lang.ClassLoaderBootstrapClassLoader(启动类加载器)的顶层加载类,由C++实现,负责加载%JAVA_HOME%/lib目录。-Xbootclasspath参数指定路径下的jar包和类或者所有类系统变量指定路径下的jar包。AppClassLoader(应用类加载器)是我们用户的加载器,负责加载当前应用类路径下的所有jar包和类。双亲委托模型当一个类加载器收到一个类加载任务时,它会先交给它的父加载器来完成,所以最后的加载任务会交给最顶层的BootstrapClassLoader,只有当父加载器无法完成加载任务时,将尝试自己加载它。但是熟悉Java的人都知道,Java中只有父类,没有母类。顾父母其实是在误导。我更愿意理解为父类委托模型。以下为官方解释。Java平台使用委托模型来加载类。基本思想是每个类加载器都有一个“父”类加载器。加载类时,类加载器首先将搜索该类的工作“委托”给其父类加载器,然后再尝试自行查找该类。Classloader加载过程protectedClassloadClass(Stringname,booleanresolve)throwsClassNotFoundException{synchronized(getClassLoadingLock(name)){//首先检查这个类是否已经加载。在JVM生命周期中,一个类只会被加载一次Classc=findLoadedClass(name);如果(c==null){longt0=System.nanoTime();try{if(parent!=null){//如果父类加载器不为空,则使用父类加载器加载c=parent.loadClass(name,false);}else{//如果父类加载器为空,则使用顶层引导加载器c=findBootstrapClassOrNull(name);}}catch(ClassNotFoundExceptione){//如果上面加载失败,继续执行}if(c==null){//如果上面代码没有加载成功,那么尝试自己加载longt1=System.纳米时间();c=findClass(名字);//这是定义类加载器;记录统计数据sun.misc.PerfCounter.getParentDelegationTime().addTime(t1-t0);sun.misc.PerfCounter.getFindClassTime().addElapsedTimeFrom(t1);sun.misc.PerfCounter.getFindClasses().increment();}}如果(解决){resolveClass(c);}返回c;双亲委派模型的好处是保证了Java程序的稳定运行,并且可以避免类的重复加载,VM通过类名和加载器来确定唯一的类,保证Java核心API不被篡改。如果不使用双亲委派模型,而是每个类加载器加载自己的类,就会出现一些问题,比如开发者定义了一个名为java.lang.Object的类,当程序运行时,会出现多个不同的Object类出现在系统中如果你不想使用双亲委派模型,如果你不想破坏双亲委派模型,只需重写ClassLoader类中的findClass()方法即可。不能被父类加载器加载的类,最终会通过这个方法加载。如果你想打破双亲委派模型,那么你需要重写loadClass()方法来自定义类加载器。自定义加载器,需要继承ClassLoader