ClassLoader類加載器

關於ClassLoader原理網上簡介頗多,可是講的好的,能讓人簡而易懂的理解的,我的以爲如下這個片博客寫的不錯。java

java虛擬機原理圖解 5. JVM類加載器機制與類加載過程linux

爲了理解本文,我從代碼角度來分析JVM加載機制和類加載過程tomcat

首先:app

  BootStrapClassLoader----引導類加載器---C++編寫,封裝入JVMeclipse

  ExtClassLoader----------擴展類加載器---Launcher內部類ui

  AppClassLoader----------應用類加載器/系統類加載器---Launcher內部this

當咱們在IJ或者eclipserun一個帶main方法的類時或者在linuxjava batchmainlua

run以前,咱們的java虛擬機是關閉的狀態。run虛擬機開啓,BootStrapClassLoader會加載{JAVA_HOME}/jre/lib下的jar包,spa

其中有一個rt.jar的包中,咱們會找到一個sun.misc.Launcher類,既然BootStrapClassLoader加載rt.jar必然會加載Launcher,.net

這裏我貼了源代碼:

 

package sun.misc;

import ...

public class Launcher {
    private static URLStreamHandlerFactory factory = new Launcher.Factory();
  //咱們能夠看出這個單例模式,私有化launcher,當BootStrap加載Launcher時,自動建立Launcher的實例
private static Launcher launcher = new Launcher(); private static String bootClassPath = System.getProperty("sun.boot.class.path"); private ClassLoader loader; private static URLStreamHandler fileHandler;   //單例模式提供的public get方法 public static Launcher getLauncher() { return launcher; }   //構造方法,會實例化內部類ExtClassLoaderAppClassLoader 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); } 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(); System.setSecurityManager(var3); } }

 

AppClassLoader and ExtClassLoader擁有相同的如下繼承關係:

AppClassLoader extends URLClassLoader extends SecureClassLoader extends ClassLoader

ExtClassLoader extends URLClassLoader extends SecureClassLoader extends ClassLoader

ClassLoader是個抽象類,可是有構造方法,以下

1 //代碼我以略掉大部分
2 public abstract class ClassLoader {
3     private final ClassLoader parent;
4 
5     private ClassLoader(Void unused, ClassLoader parent) {
6         this.parent = parent;
7      }
8 }

AppClassLoaderExtClassLoader實例化這個部分我也貼出代碼:

 

 1 static class AppClassLoader extends URLClassLoader {
 2         final URLClassPath ucp = SharedSecrets.getJavaNetAccess().getURLClassPath(this);
 3 
 4         public static ClassLoader getAppClassLoader(final ClassLoader var0) throws IOException {
 5             final String var1 = System.getProperty("java.class.path");
 6             final File[] var2 = var1 == null ? new File[0] : Launcher.getClassPath(var1);
 7             return (ClassLoader)AccessController.doPrivileged(new PrivilegedAction<Launcher.AppClassLoader>() {
 8                 public Launcher.AppClassLoader run() {
 9                     URL[] var1x = var1 == null ? new URL[0] : Launcher.pathToURLs(var2);
              //此處返回的對象根據java多態性回調用Classloader抽象類構造方法parent傳值爲var0,ExtClassLoader
10 return new Launcher.AppClassLoader(var1x, var0); 11 } 12 }); 13 } 14 15 AppClassLoader(URL[] var1, ClassLoader var2) { 16 super(var1, var2, Launcher.factory); 17 this.ucp.initLookupCache(this); 18 } 19 20 public Class<?> loadClass(String var1, boolean var2) throws ClassNotFoundException { 21 int var3 = var1.lastIndexOf(46); 22 if (var3 != -1) { 23 SecurityManager var4 = System.getSecurityManager(); 24 if (var4 != null) { 25 var4.checkPackageAccess(var1.substring(0, var3)); 26 } 27 } 28 29 if (this.ucp.knownToNotExist(var1)) { 30 Class var5 = this.findLoadedClass(var1); 31 if (var5 != null) { 32 if (var2) { 33 this.resolveClass(var5); 34 } 35 36 return var5; 37 } else { 38 throw new ClassNotFoundException(var1); 39 } 40 } else { 41 return super.loadClass(var1, var2); 42 } 43 }
 1 static class ExtClassLoader extends URLClassLoader {
 2         public static Launcher.ExtClassLoader getExtClassLoader() throws IOException {
 3             final File[] var0 = getExtDirs();
 4 
 5             try {
 6                 return (Launcher.ExtClassLoader)AccessController.doPrivileged(new PrivilegedExceptionAction<Launcher.ExtClassLoader>() {
 7                     public Launcher.ExtClassLoader run() throws IOException {
 8                         int var1 = var0.length;
 9 
10                         for(int var2 = 0; var2 < var1; ++var2) {
11                             MetaIndex.registerDirectory(var0[var2]);
12                         }
13               //此處返回的對象根據java多態性回調用Classloader抽象類構造方法,其parent傳值爲null。
14                         return new Launcher.ExtClassLoader(var0);
15                     }
16                 });
17             } catch (PrivilegedActionException var2) {
18                 throw (IOException)var2.getException();
19             }
20         }

 至此JVM類加載器初始化完畢。而後loader.loadClass();

此時咱們根據類加載規則,去加載main類,若是發現有main()方法,就開始直接執行,直到exit。

咱們須要注意的是,類加載器加載一個類時,並非去讀代碼看看那些類須要加載,這裏涉及到最重要的東西那就是:

Import,由於咱們須要的類都是引入進來的,引入包直接加載就行了。

 

setContextClassLoader能夠打破雙親加載機制。典型應用---tomcat啓動類BootStrap定義了三個自定義加載器,catalinaClassLoader  commonClassLoader sharedClassLoader......
相關文章
相關標籤/搜索