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类加载机制和原理详解
【图解版】深入分析ClassLoader类加载工作机制,从原理到JVM的装载过程,详情分析了ClassLoader加载类以及自定义类加载器的过程,不可用于商业用途,如有版权问题,请联系删除!
NULL 博文链接:https://ldbjakyo.iteye.com/blog/1046984
通过对ClassLoader中两个子类加载dex,来熟悉安卓中的apk加载流程
ClassLoader的API使用和自定义
ClassLoader类加载器讲解,理解JAVA类加载机制
类加载器是 Java 语言的一个创新,也是 Java 语言流行的重要原因之一。它使得 Java 类可以被动态加载到 Java 虚拟机中并执行。类加载器从 JDK 1.0 就出现了,最初是为了满足 Java Applet 的需要而开发出来的。Java ...
ClassLoader动态加载类 简单示例 包装tank.test; 导入java.util.Scanner; 导入tank.classloader.ClassLoaderManager; 导入tank.classloader.MyClassLoaderManager; 导入tank.classloader.SystemClassLoaderManager...
本篇文章主要给大家讲述了Java中ClassLoader类加载的原理以及用法总结,一起学习下。
该电子书详细介绍了java虚拟机类加载机制,对于深入理解jvm工作原理有很好的帮助作用,对于初学java,有一定工作经验的小伙伴来说是一本提高自身java素养,夯实自己java基本技能的“葵花宝典”。
Java 虚拟机中ClassLoader 相关简介 双亲委托机制 Android 中ClassLoader 简介
下面小编就为大家带来一篇classloader类加载器_基于java类的加载方式详解。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
jvm运行的过程中,需要载入类,而类的加载需要类加载器,本文章提供了java的类加载器的工作原理。可以使读者更加理解jvm的运行机制。
1. 加载(Loading):classpath,jar包,网络,磁盘位置下的类的class以二进制字节流读进来,在内存 2. 验证(Verification)
ClassLoader类加载器负责读取 Java 字节代码,并转换成 java.lang.Class类的一个实例。从而只有class文件被载入到了内存之后,才能被其程序所引用。所以ClassLoader就是用来动态加载class文件到内存当中用的。 ...
主要为大家解析了ClassLoader类加载源码,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
1. ClassLoader(类加载机制) 3. findLoadedClass (查找JVM已经加载过的类) 4. defineClass (定义一个Java
eclipse工程格式 博文链接:https://aga.iteye.com/blog/200818
java自定义类加载classloader文档,包括代码,以及详细的原理及过程