编程语言
首页 > 编程语言> > 25-Launcher类源码分析

25-Launcher类源码分析

作者:互联网

Launcher类源码分析

JDK开源:http://openjdk.java.net/

Launcher:

private static URLStreamHandlerFactory factory = new Launcher.Factory();
private static Launcher launcher = new Launcher();
private static String bootClassPath = System.getProperty("sun.boot.class.path");
private ClassLoader loader;
private static URLStreamHandler fileHandler;

public static Launcher getLauncher() {
   return launcher;
}

public Launcher() {
   //创建一个扩展类加载器
   Launcher.ExtClassLoader var1;
   try {
      //这里是去创建扩展类加载器,返回扩展类加载器的实例
      var1 = Launcher.ExtClassLoader.getExtClassLoader();
   } catch (IOException var10) {
      throw new InternalError("Could not create extension class loader", var10);
   }

   try {
      //这里是去创建系统类加载器的实例,这里我们可以看到,getAppClassLoader(var1)中的参数var1是
      //扩展类加载器get得到的结果,最终作为参数传递到getAppClassLoader中。
      //并且赋给了loader,而loader又是Launcher类的一个私有成员变量。
      //而且这句话也说明了, 扩展类加载器是系统类加载器的双亲!!!
      this.loader = Launcher.AppClassLoader.getAppClassLoader(var1);
   } catch (IOException var9) {
      throw new InternalError("Could not create application class loader", var9);
   }

   //Also set the conext class loader for the primordial thread
   //还为原始线程设置conext(上下文)类加载器
   Thread.currentThread().setContextClassLoader(this.loader);
   //Finally,install a security manager if requested
   //最终,如果需要,请安装安全管理器
   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);
   }
}
//调用这个方法就是返回loader(App),而 ExtClassLoader会通过getParent得到!
public ClassLoader getClassLoader() {
   return this.loader;
}

ExtClassLoader:

//这里ExtClassLoader继承了URLClassLoader,URLClassLoader又继承了SecureClassLoader,
//SecureClassLoader又继承了ClassLoader
static class ExtClassLoader extends URLClassLoader, {
   /*
   	create an ExClassLoader. The ExtClassLoader is created within a context that 
   	limits which files it can read
   	创建一扩展类加载器,ExtClassLoader是在以下上下文中创建的限制它可以读取哪些文件
   */
   public static Launcher.ExtClassLoader getExtClassLoader() throws IOException {
      final File[] var0 = getExtDirs(); //就是返回扩展类加载器所加载的那几个目录路径

      try {
         //AccessController.doPrivilege主要是做一个权限的校验
         return (Launcher.ExtClassLoader)AccessController.doPrivileged(new PrivilegedExceptionAction<Launcher.ExtClassLoader>() {
            public Launcher.ExtClassLoader run() throws IOException {
               int var1 = var0.length;

               for(int var2 = 0; var2 < var1; ++var2) {
                  MetaIndex.registerDirectory(var0[var2]);
               }
					//最终返回一个ExtClassLoader,谁调用了,返回给谁!其实就是Launcher里面的
               //var1 = Launcher.ExtClassLoader.getExtClassLoader();
               return new Launcher.ExtClassLoader(var0); 
            }
         });
      } catch (PrivilegedActionException var2) {
         throw (IOException)var2.getException();
      }
   }

   void addExtURL(URL var1) {
      super.addURL(var1);
   }

   public ExtClassLoader(File[] var1) throws IOException {
      super(getExtURLs(var1), (ClassLoader)null, Launcher.factory);
      SharedSecrets.getJavaNetAccess().getURLClassPath(this).initLookupCache(this);
   }

   //就是返回扩展类加载器所加载的那几个目录路径
   private static File[] getExtDirs() {
      //这个其实就是得到扩展类加载器所加载的那几个特定的目录路径
      String var0 = System.getProperty("java.ext.dirs");
      File[] var1;
      if (var0 != null) {
         //这里对多个路径进行分割
         StringTokenizer var2 = new StringTokenizer(var0, File.pathSeparator);
         int var3 = var2.countTokens(); //得到数目(几个路径)
         var1 = new File[var3]; //最终放在var1这个数组中

         for(int var4 = 0; var4 < var3; ++var4) {
            var1[var4] = new File(var2.nextToken());
         }
      } else {  //如果为空,就新new一个,返回回去
         var1 = new File[0];
      }

      return var1;
   }

   private static URL[] getExtURLs(File[] var0) throws IOException {
      Vector var1 = new Vector();

      for(int var2 = 0; var2 < var0.length; ++var2) {
         String[] var3 = var0[var2].list();
         if (var3 != null) {
            for(int var4 = 0; var4 < var3.length; ++var4) {
               if (!var3[var4].equals("meta-index")) {
                  File var5 = new File(var0[var2], var3[var4]);
                  var1.add(Launcher.getFileURL(var5));
               }
            }
         }
      }

      URL[] var6 = new URL[var1.size()];
      var1.copyInto(var6);
      return var6;
   }

   public String findLibrary(String var1) {
      var1 = System.mapLibraryName(var1);
      URL[] var2 = super.getURLs();
      File var3 = null;

      for(int var4 = 0; var4 < var2.length; ++var4) {
         URI var5;
         try {
            var5 = var2[var4].toURI();
         } catch (URISyntaxException var9) {
            continue;
         }

         File var6 = (new File(var5)).getParentFile();
         if (var6 != null && !var6.equals(var3)) {
            String var7 = VM.getSavedProperty("os.arch");
            File var8;
            if (var7 != null) {
               var8 = new File(new File(var6, var7), var1);
               if (var8.exists()) {
                  return var8.getAbsolutePath();
               }
            }

            var8 = new File(var6, var1);
            if (var8.exists()) {
               return var8.getAbsolutePath();
            }
         }

         var3 = var6;
      }

      return null;
   }

   private static AccessControlContext getContext(File[] var0) throws IOException {
      PathPermissions var1 = new PathPermissions(var0);
      ProtectionDomain var2 = new ProtectionDomain(new CodeSource(var1.getCodeBase(), (Certificate[])null), var1);
      AccessControlContext var3 = new AccessControlContext(new ProtectionDomain[]{var2});
      return var3;
   }

   static {
      ClassLoader.registerAsParallelCapable();
   }
}

AppClassLoader:

//The class loader used for loading from java.class.path. runs in a restricted security
//context
//用于从java.class.path加载的类加载器。在受限制的安全上下文中运行
static class AppClassLoader extends URLClassLoader {
   final URLClassPath ucp = SharedSecrets.getJavaNetAccess().getURLClassPath(this);

   public static ClassLoader getAppClassLoader(final ClassLoader var0) throws IOException {
      //和extClassLoader差不多,这里是获取系统类加载器所加载多个目录
      final String var1 = System.getProperty("java.class.path");
      final File[] var2 = var1 == null ? new File[0] : Launcher.getClassPath(var1);
      return (ClassLoader)AccessController.doPrivileged(new PrivilegedAction<Launcher.AppClassLoader>() {
         public Launcher.AppClassLoader run() {
            URL[] var1x = var1 == null ? new URL[0] : Launcher.pathToURLs(var2);
            //这里调用下面的AppClassLoader var0是扩展类加载器!
            return new Launcher.AppClassLoader(var1x, var0);
         }
      });
   }

   //这里的var2参数,就是扩展类加载器,
   AppClassLoader(URL[] var1, ClassLoader var2) {
      super(var1, var2, Launcher.factory);
      this.ucp.initLookupCache(this);
   }

   public Class<?> loadClass(String var1, boolean var2) throws ClassNotFoundException {
      int var3 = var1.lastIndexOf(46);
      if (var3 != -1) {
         SecurityManager var4 = System.getSecurityManager();
         if (var4 != null) {
            var4.checkPackageAccess(var1.substring(0, var3));
         }
      }

      if (this.ucp.knownToNotExist(var1)) {
         Class var5 = this.findLoadedClass(var1);
         if (var5 != null) {
            if (var2) {
               this.resolveClass(var5);
            }

            return var5;
         } else {
            throw new ClassNotFoundException(var1);
         }
      } else {
         return super.loadClass(var1, var2);
      }
   }

   protected PermissionCollection getPermissions(CodeSource var1) {
      PermissionCollection var2 = super.getPermissions(var1);
      var2.add(new RuntimePermission("exitVM"));
      return var2;
   }

   private void appendToClassPathForInstrumentation(String var1) {
      assert Thread.holdsLock(this);

      super.addURL(Launcher.getFileURL(new File(var1)));
   }

   private static AccessControlContext getContext(File[] var0) throws MalformedURLException {
      PathPermissions var1 = new PathPermissions(var0);
      ProtectionDomain var2 = new ProtectionDomain(new CodeSource(var1.getCodeBase(), (Certificate[])null), var1);
      AccessControlContext var3 = new AccessControlContext(new ProtectionDomain[]{var2});
      return var3;
   }

   //这里是将其注册为可以并行加载的!
   static {
      ClassLoader.registerAsParallelCapable();
   }
}

ClassLoader中初始化系统类加载器:

private static synchronized void initSystemClassLoader() {
   if (!sclSet) {
      if (scl != null)
         throw new IllegalStateException("recursive invocation");
      //得到创建的类加载器实例(其实系统类加载器,是否是扩展类加载器可以通过getParent去判别,即使用:
      //new SystemClassLoaderAction(scl)去判断)
      sun.misc.Launcher l = sun.misc.Launcher.getLauncher();
      if (l != null) {
         Throwable oops = null;
         scl = l.getClassLoader();  //得到系统类加载器
         try {
            scl = AccessController.doPrivileged(
               //就是为了处理是:scl最终返回的是用户自定义系统类加载器还是默认的AppClassLoader
               new SystemClassLoaderAction(scl));
         } catch (PrivilegedActionException pae) {
            oops = pae.getCause();
            if (oops instanceof InvocationTargetException) {
               oops = oops.getCause();
            }
         }
         //异常处理
         if (oops != null) {
            if (oops instanceof Error) {
               throw (Error) oops;
            } else {
               // wrap the exception
               throw new Error(oops);
            }
         }
      }
      sclSet = true;
   }
}

class SystemClassLoaderAction
    implements PrivilegedExceptionAction<ClassLoader> {
    private ClassLoader parent;
	 //上面调用这个实例时,将scl(系统类加载器传过来)
    SystemClassLoaderAction(ClassLoader parent) {
        this.parent = parent;
    }

    /**
    		★★★比较重要要的一段!★★★
    */
    public ClassLoader run() throws Exception {
        //自定义系统类加载器的系统属性
        String cls = System.getProperty("java.system.class.loader");
        //如果为null,说明我们没有设置前面这一句属性,
        //说明系统类加载器就是默认的AppClassLoader
        if (cls == null) { 
            return parent;
        }

        Constructor<?> ctor = Class.forName(cls, true, parent)
            .getDeclaredConstructor(new Class<?>[] { ClassLoader.class });
        ClassLoader sys = (ClassLoader) ctor.newInstance(
            //这句代码也就说明为什么自定义系统类加载器的父亲是AppClassLoader
            new Object[] { parent }); 
        //sys 也就是用户自定义的系统类加载器,将其放进上下文类加载器
        Thread.currentThread().setContextClassLoader(sys);
        return sys;
    }
}

标签:25,var1,var3,var2,Launcher,源码,new,加载
来源: https://blog.csdn.net/qq_40574305/article/details/104793544