ClassLoader


 今天在网上收集了classLoader的学习,综合了各个的博客,在此记录,

 

一、类加载结构

      1、bootstrap classloader 启动类加载器

             (1) 运行虚拟机时候,这个类加载器被加载

             (2)加载java 基本api,负责jdk_home/lib目录下的核心 api 或者-X bootclasspath 选项指定的jar包装入工作

             (3)不是java语言实现的

 

     2、extension classloader 扩展类加载器

          (1)主要负责jdk_home/lib/ext目录下的jar包或 -D java.ext.dirs 指定目录下的jar包装入工作

    

    3、system classloader   系统类加载器

         (1)主要负责java -classpath或者-Djava.class.path或者CLASSPATH操作系统属性所指定的JAR类包      所指的目录下的类与jar包装入工作

 

   4、user custom classloader  用户自定义类加载器

       (1)在程序运行期间, 通过java.lang.ClassLoader的子类动态加载class文件, 体现java动态实时类装入特性.


类机构:
 

 

 

 

二、类加载器的特性

      1、每个ClassLoader都维护了一份自己的名称空间, 同一个名称空间里不能出现两个同名的类

           这么说,我们是否可以定义一个类String?答案是可以的

 

      2、为了实现java安全沙箱模型顶层的类加载器安全机制, java默认采用了 ” 双亲委派的加载链 ” 结构.

          

 

 

 

三、Launcher

      (1)Launcher的理解

      Launcher是JVM是为我们来建立类加载器的结构的一个重要对象。

      sun.misc.Launcher ,顾名思义,当你执行java命令的时候,JVM会先使用bootstrap classloader载入并初始化一个Launcher,执行下来代码:
      System.out.println("the Launcher's classloader is "+sun.misc.Launcher.getLauncher().getClass().getClassLoader());
      结果为:
      the Launcher's classloader is null (因为是用bootstrap classloader加载,所以class loader为null)

      (2)Launcher的代码实现

             

public class Launcher  {  
   public Launcher() {  
       ExtClassLoader extclassloader;  
       try {  
           //初始化extension classloader  
           extclassloader = ExtClassLoader.getExtClassLoader();  
       } catch(IOException ioexception) {  
           throw new InternalError("Could not create extension class loader");  
       }  
       try {  
           //初始化system classloader,parent是extension classloader  
           loader = AppClassLoader.getAppClassLoader(extclassloader);  
       } catch(IOException ioexception1) {  
           throw new InternalError("Could not create application class loader");  
       }  
       //将system classloader设置成当前线程的context classloader(将在后面加以介绍)  
       Thread.currentThread().setContextClassLoader(loader);  
       ......  
   }  
   public ClassLoader getClassLoader() {  
       //返回system classloader  
       return loader;  
   }  
}  

 显然,Launcher加载了extension classloader和system classloader

 

 

四、上下文类加载器

       上述代码中setContextClassLoader 就是上下文类加载器,

       使用线程上下文类加载器, 可以在执行线程中, 抛弃双亲委派加载链模式, 使用线程上下文里的类加载器加载类。

       大部分java app服务器(jboss, tomcat..)也是采用contextClassLoader来处理web服务。

 

五、加载class的两种方式

      (1)ClassLoader.loadClass(String name);

              这种方式实现的是双亲委托方式,

public Class<?> loadClass(String name) throws ClassNotFoundException {
        return loadClass(name, false);
    }

 protected Class<?> loadClass(String name, boolean resolve)
        throws ClassNotFoundException
    {
        synchronized (getClassLoadingLock(name)) {
            // First, check if the class has already been loaded
            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) {
                    // ClassNotFoundException thrown if class not found
                    // from the non-null parent class loader
                }

                if (c == null) {
                    // If still not found, then invoke findClass in order
                    // to find the class.
                    long t1 = System.nanoTime();
                    c = findClass(name);

                    // this is the defining class loader; record the stats
                    sun.misc.PerfCounter.getParentDelegationTime().addTime(t1 - t0);
                    sun.misc.PerfCounter.getFindClassTime().addElapsedTimeFrom(t1);
                    sun.misc.PerfCounter.getFindClasses().increment();
                }
            }
            if (resolve) {
                resolveClass(c);
            }
            return c;
        }
    }

   从这上面可以看出,双亲委托方式的算法逻辑。

       (2)Class.forName(String name);

             

  public static Class<?> forName(String className)
                throws ClassNotFoundException {
        return forName0(className, true, ClassLoader.getCallerClassLoader());
    }

 /** Called after security checks have been made. */
    private static native Class<?> forName0(String name, boolean initialize,
                                            ClassLoader loader)
        throws ClassNotFoundException;

    forName方式,使用的是当前的classloader,最后是一个native方法

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值