楼主: calizi
223 0

ClassLoader [推广有奖]

  • 0关注
  • 0粉丝

学前班

40%

还不是VIP/贵宾

-

威望
0
论坛币
2 个
通用积分
0
学术水平
0 点
热心指数
0 点
信用等级
0 点
经验
30 点
帖子
1
精华
0
在线时间
0 小时
注册时间
2021-10-16
最后登录
2021-10-16

楼主
calizi 发表于 2021-10-16 14:09:26 |AI写论文

+2 论坛币
k人 参与回答

经管之家送您一份

应届毕业生专属福利!

求职就业群
赵安豆老师微信:zhaoandou666

经管之家联合CDA

送您一个全额奖学金名额~ !

感谢您参与论坛问题回答

经管之家送您两个论坛币!

+2 论坛币
ClassLoader

源码解析

我们的应用类加载器和扩展类加载器都是在Launcher类中进行初始化的

应用型加载器和扩展类加载器初始化

public Launcher() {
     Launcher.ExtClassLoader var1;
     try {
         // 创建ExtClassLoader
         var1 = Launcher.ExtClassLoader.getExtClassLoader();
     } catch (IOException var10) {
         throw new InternalError("Could not create extension class loader", var10);
     }

     try {
         // 创建AppClassLoader
         this.loader = Launcher.AppClassLoader.getAppClassLoader(var1);
     } catch (IOException var9) {
         throw new InternalError("Could not create application class loader", var9);
     }
     // 设置上下文加载器为AppClassLoader,这里就可以解释为什么我们getContextClassLoader的时候为什么是AppClassLoader加载器了
     Thread.currentThread().setContextClassLoader(this.loader);
     String var2 = System.getProperty("java.security.manager");
     if (var2 != null) {
         SecurityManager var3 = null;
         if (!"".equals(var2) && !"default".equals(var2)) {
             try {
                 var3 = (SecurityManager)this.loader.loadClass(var2).newInstance();
             } catch (IllegalAccessException var5) {
             } catch (InstantiationException var6) {
             } catch (ClassNotFoundException var7) {
             } catch (ClassCastException var8) {
             }
         } else {
             var3 = new SecurityManager();
         }
         if (var3 == null) {
             throw new InternalError("Could not create SecurityManager: " + var2);
         }
         System.setSecurityManager(var3);
     }
}

我们详解4个方法,这些方法都是在抽象类ClassLoader里面

  • loadClass():真正双亲委派机制的代码实现

  • findClass():查找二进制名称为name的类,返回结果为java.lang.Class类的实例。这是一个受保护的方法, JVM鼓励我们重写此方法,需要自定义加载器遵循双亲委托机制,该方法会在检查完父类加载器之后被loadClass()方法调用。

    // 该方法在ClassLoader中是一个空方法,真正的实现实在URLClassLoader中
    protected Class<?> findClass(final String name)
  • defineClass():根据给定的字节数组b转换为Class的实例,off 和1en参数表示实际Class信息在byte数组中的位置和长度,其中byte数组b是ClassLoader从外部获取的。这是受保护的方法,只有在自定义ClassLoader子类中可以使用。

    protected final Class<?> defineClass(String name, byte[] b, int off, int len, CodeSource cs)
  • resolveClass():解析类


AppClassLoader中的loadclass

// resolve判断是否需要解析
protected Class<?> loadClass(String name, boolean resolve)
     throws ClassNotFoundException
{
     synchronized (getClassLoadingLock(name)) {
         // 检查是否被加载过,如果没有被加载就返回null
         Class<?> c = findLoadedClass(name);
         if (c == null) {
             long t0 = System.nanoTime();
             try {
                 // 判断是否存在父级加载器
                 if (parent != null) {
                     // 存在就先用父类加载器进行加载
                     c = parent.loadClass(name, false);
                 } else {
                     // 调用引导类加载器进行加载
                     c = findBootstrapClassOrNull(name);
                 }
             } catch (ClassNotFoundException e) {
             }
             // 如果没有被父级加载就开始加载
             if (c == null) {
                 long t1 = System.nanoTime();
                 c = findClass(name);

                 sun.misc.PerfCounter.getParentDelegationTime().addTime(t1 - t0);
                 sun.misc.PerfCounter.getFindClassTime().addElapsedTimeFrom(t1);
                 sun.misc.PerfCounter.getFindClasses().increment();
             }
         }
         // 是否解析类
         if (resolve) {
             resolveClass(c);
         }
         return c;
     }
}

SecureClassLoader和URLClassLoader

接着SecureClassLoader扩展了ClassLoader, 新增了几个与使用相关的代码源(对代码源的位置及其证书的验证)和权限定义类验证(主要指对class源码的访问权限)的方法,一 般我们不会直接跟这个类打交道,更多是与它的子类URLClassLoader有所关联。

前面说过,ClassLoader是一个抽象类,很多方法是空的没有实现,比如findClass()、findResource()等。而URLClassLoader这个实现类为这些方法提供了具体的实现。并新增了URLClassPath类协助取得Class字节码流等功能。在编写自定义类加载器时,如果没有太过于复杂的需求,可以直接继承URLClassLoader类, 这样就可以避免自己去编写findClass()方法及其获取字节码流的方式,使自定义类加载器编写更加简洁。


Class.forName() 与ClassLoader.loadClass():

  • Class.forName():是一个静态方法,最常用的是Class.forName(String className) ;根据传入的类的全限定名返回一个Class对象。该方法在将Class文件加载到内存的同时,会执行类的初始化。如:Class.forName("com.atguigu.java.HelloWorld");

  • ClassLoader.loadClass(): 这是一个实例方法,需要一个ClassLoader 对象来调用该方法。该方法将Class文件加载到内存时,并不会执行类的初始化,直到这个类第一次使用时才进行初始化。该方法因为需要得到一个ClassLoader 对象,所以可以根据需要指定使用哪个类加载器.如: ClassLoader c1=.......; c1.loadClass("com.atguigu.java.HelloWorld");



二维码

扫码加我 拉你入群

请注明:姓名-公司-职位

以便审核进群资格,未注明则拒绝

关键词:Loader load der Application delegation

您需要登录后才可以回帖 登录 | 我要注册

本版微信群
jg-xs1
拉您进交流群
GMT+8, 2025-12-28 13:24