`

Classloader委托加载模型的反向问题

    博客分类:
  • jvm
阅读更多

Classloader委托加载模型的反向问题 英文就是 back door around the classloading delegation scheme

当A类引用到B类,那么加载B类的classloader就是当时A的classloader,下面一个例子

 

public class A {
	public static void main(String[] args) {
	     System.out.println("class A loaded by " + A.class.getClassLoader());
	        //在调用下面的语句是,B的class会被加载,而加载器则是加载A的classloader
		 B b = new B();
		 b.methodB();
	}

}

 

public class B {

	public void methodB() {
	     System.out.println("class B loaded by " + B.class.getClassLoader());
	}

}

    上面打印输出如下:

    class A loaded by sun.misc.Launcher$AppClassLoader@192d342
    class B loaded by sun.misc.Launcher$AppClassLoader@192d342

 

    可是假使我们有3个类,A,B,C,  A和C在classpath下面,B不在classpath下面,而在C:\jdk1.6.0_29\jre\lib\ext 

    \classes下面,上代码

 

public class A {
	public static void main(String[] args) {
		System.out.println("class A loaded by " + A.class.getClassLoader());
		B b = new B();
		b.methodB();
	}
	
}

 

public class B {

	public void methodB() {
		System.out.println("class B loaded by " + B.class.getClassLoader());

		C c = new C();
		c.methodc();
	}

}

 

public class C {

	public void methodc() {
		System.out.println("class C loaded by " + C.class.getClassLoader());
	}

}

    将A和C放入C盘根目录,B放入C:\jdk1.6.0_29\jre\lib\ext\classes

进入cmd,执行结果如下

     C:\>java A
class A loaded by sun.misc.Launcher$AppClassLoader@192d342
class B loaded by sun.misc.Launcher$ExtClassLoader@6b97fd

Exception in thread "main" java.lang.NoClassDefFoundError: C
        at B.methodB(B.java:8)
        at A.main(A.java:6)
Caused by: java.lang.ClassNotFoundException: C
        at java.net.URLClassLoader$1.run(URLClassLoader.java:202)
        at java.security.AccessController.doPrivileged(Native Method)
        at java.net.URLClassLoader.findClass(URLClassLoader.java:190)
        at sun.misc.Launcher$ExtClassLoader.findClass(Launcher.java:229)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:306)
        at java.lang.ClassLoader.loadClass(ClassLoader.java:247)
        ... 2 more

 

之所以出现A和B都加载了,而C加载不了,是因为委托模型不能反向,因为加载B的classloader是ExtClassLoader, 所以接下来的C也由此classloader加载,按照委托模型,ExtClassLoader会先交由BootStrapClassLoader搜其管辖目录搜索然后由本身在在 C:\jdk1.6.0_29\jre\lib\ext\下搜索,即便如果都搜索不到C,也不会交由AppClassloader加载,因为委托模型只能由当前classloader向上不能向下(而这里的C只能由Appclassloader加载)

 

如何能让B加载到C呢?只能变换classloader

修改后的B代码如下

public class B {

	public void methodB() {
		System.out.println("class B loaded by " + B.class.getClassLoader());
		ClassLoader cl = Thread.currentThread().getContextClassLoader();
		System.out.println("the thread context classloader was " + cl);


		try {
			Class clazzc = Class.forName("C", true, cl); 
			Method m = clazzc.getMethod("methodC", null);
			Object obj = clazzc.newInstance();
			m.invoke(obj, null);
		} catch (Exception e) {
			e.printStackTrace();
		}

	}

}

   Every thread has a classloader associated with it . If the thread is a main thread then the class  

   loader associated with it a System Class Loader. 具体Thread.currentThread(). getContextClassLoader

   方法参考文档,在这里他会返回AppClassloader

 

同上方法运行A类在cmd,得到

C:\>java A
class A loaded by sun.misc.Launcher$AppClassLoader@192d342
class B loaded by sun.misc.Launcher$ExtClassLoader@6b97fd
the thread context classloader was sun.misc.Launcher$AppClassLoader@192d342
class C loaded by sun.misc.Launcher$AppClassLoader@192d342

 

 

这种需求哪里会用到?

比如java.sql.Drivermanager是rt.jar中的类,而用户classpath下面的具体driver则是classpath下面的类,则需要用到此方法,具体参见DriverManager.getConnection(x,x,x)方法

也就是说核心类库中调用用户代码之前都需要变更classloader

 

下面文章可以参考:

http://hllvm.group.iteye.com/group/topic/38709

http://stackoverflow.com/questions/13307885/could-you-please-explain-a-code-snippet-in-drivermanager-class-related-to-classl/13308729#13308729

http://stackoverflow.com/questions/1771679/difference-between-threads-context-class-loader-and-normal-classloader

http://www.blogjava.net/lihuaxajh/articles/94371.html

分享到:
评论

相关推荐

    ClassLoader类加载机制和原理详解

    双亲委派模型使得系统类(如java.*开头的类)由Bootstrap ClassLoader加载,而用户自定义类由应用程序类加载器(AppClassLoader)加载。这避免了类的冲突,保持了系统类库的稳定性。但有时我们可能需要打破这种模型...

    使用classloader动态加载Class

    2. **双亲委派模型**:Java的类加载机制遵循双亲委派模型,即当一个类加载器接收到加载类的请求时,它会先委托给父类加载器去加载,只有当父类加载器无法加载时,当前类加载器才会尝试自己加载。这种设计有助于防止...

    【图解版】深入分析ClassLoader类加载工作机制

    【图解版】深入分析ClassLoader类加载工作机制,从原理到JVM的装载过程,详情分析了ClassLoader加载类以及自定义类加载器的过程,不可用于商业用途,如有版权问题,请联系删除!

    ClassLoader类加载器

    总结来说,ClassLoader是Java运行时环境的重要组件,它按照委托模型加载类,提供了扩展和自定义的可能性。理解和掌握ClassLoader的工作原理以及如何自定义,对于提升Java应用的灵活性和安全性具有重要意义。

    ClassLoader动态加载dex

    在Android系统中,ClassLoader是Java类加载器的一种实现,它负责加载应用的代码资源,包括类、库等。当我们谈论"ClassLoader动态加载dex"时,实际上是指在Android应用程序运行时,通过自定义的ClassLoader来动态加载...

    java的ClassLoader类加载器机制

    在 JVM 运行过程中,类加载器会形成一个层次结构,包括引导类加载器(Bootstrap ClassLoader)、扩展类加载器(Extension ClassLoader)和系统类加载器(System ClassLoader)。 引导类加载器(Bootstrap ...

    ClassLoader运行机制 自己写的

    这意味着当一个ClassLoader尝试加载某个类时,它首先会将任务委托给其父ClassLoader。如果父ClassLoader找不到该类,子ClassLoader才会尝试自己去加载。这个机制保证了系统类(如`java.lang.Object`)只被加载一次,...

    Java ClassLoader定制实例

    接着,Extension ClassLoader加载扩展类库,然后是App ClassLoader加载应用程序的类路径下的类。每个ClassLoader都有其父ClassLoader,它们形成了一个层次结构,子ClassLoader可以委托父ClassLoader去加载类,避免了...

    S18-ClassLoader类加载流程1

    在这个过程中,类加载器(ClassLoader)扮演了核心角色。本文将详细讲解类加载的流程、类加载器的层次结构以及双亲委派模型。 1. **类加载的生命周期** 类的生命周期包括7个阶段:加载、验证、准备、解析、初始化...

    Java中ClassLoader类加载学习总结

    但是,这种做法需要非常小心,因为破坏双亲委派模型可能会导致类加载过程中的问题。 知识点五:ClassLoader类的抽象性 ClassLoader类是一个抽象类,实际在使用时候会写个子类,这个方法会按照需要被重写,来完成...

    ClassLoader类加载机制

    类加载器是 Java 语言的一个创新,也是 Java 语言流行的重要原因之一。它使得 Java 类可以被动态加载到 Java 虚拟机中并执行。类加载器从 JDK 1.0 就出现了,最初是为了满足 Java Applet 的需要而开发出来的。Java ...

    JVM ClassLoader简析

    这种委托加载机制保证了类的唯一性,防止了同一个类被不同ClassLoader加载两次的问题。 ClassLoader还有自定义的概念,允许开发者创建自己的ClassLoader来实现特定的加载逻辑。例如,从网络、数据库或特定文件系统...

    classloader类加载器_基于java类的加载方式详解

    比如,如果用户尝试使用Application ClassLoader加载rt.jar中的类,这个请求会被委派到Extension ClassLoader,最终到达Bootstrap ClassLoader,它会首先检查自己是否已经加载了这个类,如果已经加载,那么就不会...

    自定义classloader的使用

    Java的类加载机制遵循双亲委派模型,即当一个类加载器需要加载类时,它首先委托父类加载器尝试加载,只有当父类加载器无法加载时,才会尝试自己加载。这种设计避免了类的重复加载,并确保了核心类库的唯一性。 二、...

    ClassLoader:ClassLoader动态加载类

    ClassLoader动态加载类 简单示例 包装tank.test; 导入java.util.Scanner; 导入tank.classloader.ClassLoaderManager; 导入tank.classloader.MyClassLoaderManager; 导入tank.classloader.SystemClassLoaderManager...

    Tomcat加载顺序

    与Common ClassLoader类似,但它的优先级更高,这意味着如果在两个目录下有同名的类,Shared ClassLoader加载的类将被优先考虑。 #### 6. WebApp ClassLoader WebApp ClassLoader是最底层的类加载器,它负责加载每...

    ClassLoader

    通过对`ClassLoader`的基本概念、工作原理、双亲委托机制以及不同类型的类加载器的了解,我们可以更好地理解Java类加载的过程及其背后的设计哲学。这对于深入理解Java虚拟机的内部机制以及开发高质量的应用程序都至...

    ClassLoader(类加载机制)1

    Bootstrap ClassLoader负责加载JDK的核心库,Extension ClassLoader加载Java的扩展库,而App ClassLoader则加载应用的类路径下的类。用户还可以自定义类加载器,用于加载特定位置或格式的类。 2. **Java类** Java...

    Java ClassLoader学习总结

    ClassLoader 中的 loadClass 方法是加载类的核心方法,该方法首先检查该 name 指定的 class 是否有被加载,如果没有加载,则委托它的双亲 ClassLoader 进行加载,只有当双亲 ClassLoader 无法加载成功后,才会由自己...

    java ClassLoader机制及其在OSGi中的应用

    在该模型下,当一个ClassLoader收到加载类的请求时,它首先会委托父加载器去尝试加载,只有当父加载器无法加载时,当前加载器才会尝试自己加载。这样设计避免了类的重复加载,并确保了核心类库的唯一性。 四、...

Global site tag (gtag.js) - Google Analytics