ClassLoader总结

转载自:

    http://www.iteye.com/topic/136427
    http://blog.csdn.net/lovingprince/article/details/4238695
    http://www.blogjava.net/lhulcn618/archive/2006/05/25/48230.html   

Java类加载器

        Java中主要有三种类加载器,如下:

    bootstrap classloader        引导类加载器,加载 JAVA_HOME/lib目录下的jar包(Java核心API)
             |
    extension classloader        扩展类加载器,加载JAVA_HOME/lib/ext下的jar包(扩展API)
             |
    system classloader           应用类加载器,加载classpath下的类
   
    system classloader 的父加载器是   extension classloader
    extension classloader 的父加载器是 bootstrap classloader
    这里的父子关系不是Java的类继承关系,是一种逻辑上的父子关系( bootstrap classloader是有C++编写的)
        
    我们已经知道Java的类装载器体系结构为树状,
    多个类装载器可以指定同一个类装载器作为自己的父类,每个子类装载器就是树状结构的一个分支,
    当然它们又可 以个有子类装载器类装载器,类装载器也可以没有父类装载器,这时Bootstrap类装载器将作为       它的隐含父类,实际上Bootstrap类装载器是所有 类装载器的祖先,也是树状结构的根。


Java类的加载使用双亲委派机制:

    双亲委派机制即一个类加载器要加载类时,先查看其父加载器是否加载过此类,若加载过,直接返回;若父加载     器也未加载,则父加载器会询问其父加载器,直到询问到根加载器(Bootstrap classLoader)
    若父加载器(以及父加载器的父加载器)未加载,则当前加载器自己加载,若自己也无法加载,则抛出异常                   ClassNotFoundException NoClassDefFoundError                    
              
     threadContextClassLoader 指定执行线程中的类由哪个加载器加载
          
     JVM启动时会先使用bootstrap classloader载入并初始化一个Launcher
     Launcher 会根据系统和命令设定初始化好class loader结构,JVM就用它来获得extension classloader和        system classloader,并载入所有的需要载入的Class
          
     //同时Launcher会将system classloader设置成当前线程的context classloader
     Thread.currentThread().setContextClassLoader(loader);

       
     因此:

        我们在编写Java程序,加载我们创建的类时,一般使用的system classloader(应用类加载器)

        除非我们自定义一个classLoader(可通过继承URLClassLoader,通过文件路径查找加载类),

        并使用它来加载类
            
        我们在多线程编程中new Thread的时候,线程对象初始化调用init方法时候,

        也会设置contextClassLoader的, Thread类init方法摘要如下:

private void init(ThreadGroup g, Runnable target, String name,long stackSize) {
    Thread parent = currentThread();					
    //省略 					
    if (security == null || isCCLOverridden(parent.getClass()))
	this.contextClassLoader = parent.getContextClassLoader();
    else
	this.contextClassLoader = parent.contextClassLoader;			    
    //省略   				    
}

            转载自:http://blog.csdn.net/lovingprince/article/details/4242497

要理类加载体系结构,就必须清楚如下几点比较基本的原则。(下面类加载器 简写为cl(classLoader))

1、cl是一种父子树形结构(注:这里不是指类继承的父子关系)

2、父cl无法看到子cl加载的类

3、虚拟机遵守双亲委托加载原则,即任何子cl必须首先委托父cl先加载需要的类,当父cl加载不到时再由子cl 

亲自加载(这是一个递归过程,即父cl如果还有父cl2,那么父cl 又委托给父cl2,依次类推,直到根为止, 

如果父cl已经加载过需要的类cl,则子cl直接使用即可)

4、全盘负责:一个classloader加载一个class后,这个class所引用或者依赖的类也由这个classloader载入,

除非显示的用另一个classloader载入 

5、类在虚拟机中的标志出来是 : cl实例号+包名+类名,因此不同的cl实例加载相同的类在虚拟机中表现出来

不同的。这就是为什么多个cl加载同一个类有时候会出现转换 异常的ClassCastException的原因         

   

自定义类加载器:

编写我们自己的类加载器,必须继承ClassLoader,然后覆盖findClass()方法。

ClassLoader超类的loadClass方法用于将类的加载操作委托给父类加载器去进行,只有该类尚未加载并且父类加

载器也无法加载该类时,才调用findClass()方法。

如果要实现该方法,必须做到以下几点:

(1)为来自本地文件系统或者其他来源的类加载其字节码

(2)调用ClassLoader超类的defineClass()方法,向虚拟机提供字节码

           转载自:

http://www.cnblogs.com/feiling/archive/2012/08/29/2662909.html
http://sudalyl.iteye.com/blog/1126306


应用 :关于字节码class在网络传递问题,两个系统经过网络传输一个类,一端可以加密class字节码,

然后另 外一端接收后解密,解密后用自定义的加载器加载类(保证了传输的安全性)

参见http://www.shangxueba.com/jingyan/91106.html          


以下根据两种自定义类加载器实现方式,参照源码的一些理解:

CompileClassLoader extends ClassLoader  参见原文: http://sudalyl.iteye.com/blog/1126306

HotSwapClassLoader extends URLClassLoader  (URLClassLoader也继承自ClassLoader)        

参见原文:  http://www.iteye.com/topic/136427

   CompileClassLoader 重写的是findClass方法

HotSwapClassLoader 重写的是loadClass方法  


自定义的classLoader都是调用loadClass方法加载类的 

系统抽象类public abstract class ClassLoader中的loadClass方法实现方式是:

先委派给双亲加载,若已加载则返回;否则自己加载调用findClass加载类,以下是源码

 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) {
		     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.
	           c = findClass(name);
	      }
	}
	if (resolve) {
		 resolveClass(c);
	}
	return c;
}

  
系统抽象类public abstract class ClassLoader中的findClass方法没有具体实现,只是抛出异常

URLClassLoader实现了findClass方法

分析两个自定义的加载器:

CompileClassLoader extends ClassLoader

HotSwapClassLoader extends URLClassLoader  (URLClassLoader也继承自ClassLoader)

CompileClassLoader 重写的是findClass方法,这种自定义方式还是委派给双亲先加载,只不过实现了 

自己的加载 方式即实现了findClass方法

若有个类A希望用自定的CompileClassLoader类加载器加载,

前提是系统加载器尚未加载该类(因为这个 自定义类加载器还是委派了双亲),

否则无法使用自定义的类加载器加载

  HotSwapClassLoader 重写的是loadClass方法   这种方式没有委派双亲,

而且直接父类URLClassLoader也实现了findClass方法,

所以推荐使用这种方式自定义类加载器


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Android中的ClassLoader命名空间是指在Android应用程序中加载不同组件(如Activity、Service、BroadcastReceiver等)时的加载环境和隔离机制。在Android中,每个应用程序组件都有自己的ClassLoader实例,用于加载和管理其依赖的ClassLoader命名空间的主要作用是隔离不同应用程序组件之间的加载,防止的冲突和污染。每个应用程序组件运行在独立的ClassLoader实例中,这样它们就能够加载和使用自己的,而不会被其他组件中的所影响。 ClassLoader命名空间还提供了加载的灵活性和扩展性。可以通过ClassLoader的机制在不同的ClassLoader实例中加载不同版本的同一个,从而避免了的冲突。也可以使用自定义的ClassLoader实现自定义的加载逻辑,例如从网络等外部来源加载文件。 Android应用程序中的ClassLoader命名空间是由Android系统提供的ClassLoader框架实现的。在Android中,应用程序组件的ClassLoader实例是基于父加载器(Parent ClassLoader)进行的,这样可以继承和共享父加载器加载的,提高的加载效率和资源利用率。 总结来说,Android中的ClassLoader命名空间是为了实现应用程序组件之间的加载隔离和灵活性而设计的,每个应用程序组件都有自己的ClassLoader实例,可以加载和管理自己的。这种ClassLoader命名空间的设计使得Android应用程序能够在多组件环境下更加稳定和可扩展。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值