您好,欢迎来到锐游网。
搜索
您的当前位置:首页ClassLoader的加载过程及分析一

ClassLoader的加载过程及分析一

来源:锐游网

一,ClassLoader的大体过程

 

如图:

详解:

 

 

 虚拟机一启动,会先做一些初始化的动作。一旦初始化动作完成之后,就会产生第一个类别加载器,即所谓的Bootstrap Loader,Bootstrap Loader 是由C++ 所撰写而成,这个Bootstrap Loader所做的初始工作中,除了也做一些基本的初始化动作之外,最重要的就是加载定义在sun.misc 命名空间底下的Launcher.java 之中的ExtClassLoader( 因为是inner class ,所以编译之后会变成Launcher$ExtClassLoader.class) ,并设定其Parent 为null,代表其父加载器为Bootstrap Loader 。然后Bootstrap Loader ,再要求加载定义于sun.misc 命名空间底下的Launcher.java 之中的AppClassLoader( 因为是inner class,所以编译之后会变成Launcher$AppClassLoader.class) ,并设定其Parent 为之前产生的ExtClassLoader 实例。

 

 

 

由以上可以看出,classLoader是由下向上查找,上层的不能向下查找。

 

二,ClassLoader中类的关系

 

如图:

详解:

 

 AppClassLoader 和ExtClassLoader 都是URLClassLoader 的子类别。由于它们都是URLClassLoader 的子类别,所以它们也应该有URL 作为搜寻类别档的参考,由原始码中我们可以得知,AppClassLoader 所参考的URL 是从系统参java.class.path 取出的字符串所决定,而java.class.path 则是由我们在执行java.exe 时,利用 –cp 或-classpath 或CLASSPATH 环境变量所决定。

 

ClassLoader的loadClass代码:

 

 

Java代码  
protected synchronized Class<?> loadClass(String name, boolean resolve)
	throws ClassNotFoundException
    {
	// First, check if the class has already been loaded
       //类是否被加载过
	Class c = findLoadedClass(name);
	if (c == null) {
	    try {
		if (parent != null) {
                  //到parentclassloader中去查找(像这个parent还有parent递归方式进行查找)
		    c = parent.loadClass(name, false);
		} else {
                  //启动类加载器进行加载
		    c = findBootstrapClass0(name);
		}
	    } catch (ClassNotFoundException e) {
	        // If still not found, then invoke findClass in order
	        // to find the class.
              //当一直都没有找到时,启动当前类的findClass进行查找
             //这个通常也是我们扩展的地方
	        c = findClass(name);
	    }
	}
	if (resolve) {
	    resolveClass(c);
	}
	return c;
    }

 


详解:
java文件的编译和Class的载入执行,都是使用Launcher初始化的appclassloader作为类载入器的,我们无法动态的改变App classloader,更无法让JVM使用我们自己的classloader来替换system classloader,根据全盘负责原则,就了编译和运行时,我们无法直接显式的使用一个system classloader寻找不到的Class,即我们只能使用Java核心类库,扩展类库和CLASSPATH中的类库中的Class。
而且我们也无法载入以java.lang....开头的包,进行了

 

 

三,分析及证明:

可以用最底层的ClassLoader得到某一个类(Test)时,Test.class.getClassLoader()就可知当前类在哪一个层次的ClassLoader下被加载

 

1,BootStrapClassLoader

 

Java代码  
  1.     Class clazz=Class.forName("java.lang.Object");   
  2.     System.out.println(clazz.getClassLoader());   
  3.   
  4.    //输出为null,因为bootstrap在java中不是类,而是由c++编写的   
  5.   
  6.   
  7.      URL[] urls=sun.misc.Launcher.getBootstrapClassPath().getURLs();   
  8.           for (int i = 0; i < urls.length; i++) {   
  9.             System.out.println(urls[i].getFile());   
  10.           }//用这个进行查找bootstrap所加载的是哪些jar包  
	Class clazz=Class.forName("java.lang.Object");
	System.out.println(clazz.getClassLoader());

   //输出为null,因为bootstrap在java中不是类,而是由c++编写的


     URL[] urls=sun.misc.Launcher.getBootstrapClassPath().getURLs();
          for (int i = 0; i < urls.length; i++) {
            System.out.println(urls[i].getFile());
          }//用这个进行查找bootstrap所加载的是哪些jar包

 

2,ExtClassLoader

 

Java代码  
  1. clazz = Class.forName("sun.net.spi.nameservice.dns.DNSNameService");     
  2.             clazzLoader = clazz.getClassLoader();     
  3.             System.out.println(" sun.net.spi.nameservice.dns.DNSNameService's loader is  "     
  4.                             + clazzLoader);     
  5. //在些可以说明ExtClassLoader所加载的类  
clazz = Class.forName("sun.net.spi.nameservice.dns.DNSNameService");  
            clazzLoader = clazz.getClassLoader();  
            System.out.println(" sun.net.spi.nameservice.dns.DNSNameService's loader is  "  
                            + clazzLoader);  
//在些可以说明ExtClassLoader所加载的类

 3,AppClassLoader

 当前工程中class与lib都是用此Loader加载

可以通过ClassLoader.getSystemClassLoader()可以获取到AppClassLoader的

4,DefineClassLoader

可以继承URLClassLoader或ClassLoader

当继承ClassLoader重写findClass()方法,parent会相应是AppClassLoader-->ExtClassLoader-->BootStrapClassLoader

 

URLClassLoader可以直接设置url即可

 

 

问题:

由于自己自定义了一个DefineClassLoader替代了加载ant的ClassLoader,另外添加自己jar包,

但是在执行ant编译时,要执行tools.jar里的javac类,在执行javac这个类时,是处在AppClassLoader

下,找不到我添加的DefineClassLoader的jar包

 

------------------------------------------------

其他一些相应的操作(参考)

 


因篇幅问题不能全部显示,请点此查看更多更全内容

Copyright © 2019- ryyc.cn 版权所有 湘ICP备2023022495号-3

违法及侵权请联系:TEL:199 1889 7713 E-MAIL:2724546146@qq.com

本站由北京市万商天勤律师事务所王兴未律师提供法律服务