第一部分:java.lang.ClassLoader

类加载器(class loader)用来加载 Java 类到 Java 虚拟机中。一般来说,Java 虚拟机使用 Java类的方式如下:Java 源程序(.java 文件)在经过 Java 编译器编译之后就被转换成 Java 字节代码(.class文件)。类加载器负责读取 Java 字节代码,并转换成 java.lang.Class 类的一个实例。每个这样的实例用来表示一个 Java类。通过此实例的 newInstance()方法就可以创建出该类的一个对象。实际的情况可能更加复杂,比如 Java字节代码可能是通过工具动态生成的,也可能是通过网络下载的。基本上所有的类加载器都是 java.lang.ClassLoader 类的一个实例

构造函数

publicabstractclassClassLoaderprivatestaticnativevoidregisterNatives();static{registerNatives();}privateClassLoader(Voidunused,ClassLoaderparent){this.parent=parent;if(ParallelLoaders.isRegistered(this.getClass())){parallelLockMap=newConcurrentHashMap<>();package2certs=newConcurrentHashMap<>();domains=Collections.synchronizedSet(newHashSet<ProtectionDomain>());assertionLock=newObject();}else{//nofiner-grainedlock;lockontheclassloaderinstanceparallelLockMap=null;package2certs=newHashtable<>();domains=newHashSet<>();assertionLock=this;}}


2.loadClass方法,该方法为类加载器的主要方法,具体代码如下:


protectedClass<?>loadClass(Stringname,booleanresolve)throwsClassNotFoundException{//1.异步保护,防止重复加载同一个classsynchronized(getClassLoadingLock(name)){//2.首先,检查是否类已经被加载过了Class<?>c=findLoadedClass(name);if(c==null){//2.1如果该类未被加载过//2.1.1System.nanoTime()这个方法主要是返回一个系统计时器的当前值,以毫微秒为单位。但是不能用作来计算当前时间,只能通过end-start算出间隔时间longt0=System.nanoTime();try{if(parent!=null){//2.1.2如果有父加载器,即父加载器不为初始加载器,则递归父加载器查看是否加载过c=parent.loadClass(name,false);}else{//2.1.3如果没有父加载器,即父加载器为初始加载器,查找类是否加载,具体看方法c=findBootstrapClassOrNull(name);}}catch(ClassNotFoundExceptione){//ClassNotFoundExceptionthrownifclassnotfound//fromthenon-nullparentclassloader}if(c==null){//2.1.4如果还是没有该类,则运行findClass方法加载,该方法为虚方法longt1=System.nanoTime();c=findClass(name);//thisisthedefiningclassloader;recordthestatssun.misc.PerfCounter.getParentDelegationTime().addTime(t1-t0);sun.misc.PerfCounter.getFindClassTime().addElapsedTimeFrom(t1);sun.misc.PerfCounter.getFindClasses().increment();}}if(resolve){//解析class,resolve默认为falseresolveClass(c);}returnc;}}


3.getClassLoadingLock(name)方法

protectedObjectgetClassLoadingLock(StringclassName){Objectlock=this;if(parallelLockMap!=null){ObjectnewLock=newObject();lock=parallelLockMap.putIfAbsent(className,newLock);if(lock==null){lock=newLock;}}returnlock;}




4.findLoadedClass(name)方法

protectedfinalClass<?>findLoadedClass(Stringname){if(!checkName(name))returnnull;returnfindLoadedClass0(name);}privatenativefinalClass<?>findLoadedClass0(Stringname);


5.findBootstrapClassOrNull(name)方法

privateClass<?>findBootstrapClassOrNull(Stringname){if(!checkName(name))returnnull;returnfindBootstrapClass(name);}//returnnullifnotfoundprivatenativeClass<?>findBootstrapClass(Stringname);


6.findClass(name)方法,该方法在ClassLoader中没有具体实现,因此根据不同的情况会重写该方法进行不同情况的判断。

protectedClass<?>findClass(Stringname)throwsClassNotFoundException{thrownewClassNotFoundException(name);}

7.resolveClass(Class<?> c)方法

protectedfinalvoidresolveClass(Class<?>c){resolveClass0(c);}privatenativevoidresolveClass0(Class<?>c);

8.defineClass方法,主要是将字节码class文件进行实例为Class实例。该方法不可覆盖,我们在继承ClassLoader的时候,会重写findClass方法将相关文件转换成jvm可识别的Class实例。必须要在重写的findClass中调用defineClass才可以完成转换的逻辑。

protectedfinalClass<?>defineClass(Stringname,byte[]b,intoff,intlen)throwsClassFormatError{returndefineClass(name,b,off,len,null);}

protectedfinalClass<?>defineClass(Stringname,byte[]b,intoff,intlen,ProtectionDomainprotectionDomain)throwsClassFormatError{protectionDomain=preDefineClass(name,protectionDomain);Stringsource=defineClassSourceLocation(protectionDomain);Class<?>c=defineClass1(name,b,off,len,protectionDomain,source);postDefineClass(c,protectionDomain);returnc;}

9.ClassLoader类的相关测试。