如果对classloader一点都不了解的,点击看以前准备的资料 http://my.oschina.net/xpbob/blog/603868
自我感觉还是说清楚什么是classloader的问题。
先基本说说我们能用到classloader的地方。稍微做一下区分。
这是我们最常见的用法了,java api文档明确指出,等效Class.forName(className, true, currentLoader)。简单说就是加载当前类的classloader来加载你需要的类。这个用法给人一种错觉,就是只要调用就会成功,让我们不知道classloader的存在。
这个用法就比第一个好很多,起码开始介入classloader了,这个是由加载class(具体就是A.class等等)的类加载器加载指定类了。
直接拿系统classloader,一般情况都是AppClassLoader。只要没有自定义classloader,调用这个就基本没有加载不到的,除非压根不在classpath上。
线程上下文加载器,下面具体说。
类加载器默认遵循双亲委托和加载到类的加载器加载依赖类两个准则。这个类的效果就是为了解决当父类加载器加载到的类依赖子类加载器的情况。就是如下一个例子。
Aclassloader是Bclassloader的父,Aclassloader的加载路径是x.class,x.class依赖y.class,Bclassloader的加载路径是y.class。现在开始加载x.class。 Aclassloader加载到了,开始加载y.class,Aclassloader遵循双亲委托,继续让父找,这样就会出现class not find 的问题。
解决方法就是依靠getContextClassLoader。很多帖子都说他可以解决这个问题。但是基本都是从官方文档里摘的,所以网上出现了一些提问,就是为什么设置了不生效的问题。
Q:
直接在线程上设置自定义的classloader,然而在线程里class.forname,new object,都没有发现作用。
A:
这两种情况都是当前类加载器加载的,当然没用。
Q:
设置之后是会加入到系统的调用中吗
A:
javase中的classloader机制中没有threadcontextclassloader的委托,这个也是不希望写到自定义的classloader中的。在ee的was中,这个用法都是显示调用的,就是获取出classloader然后loadClass。直接反射创建对象。
Q:
真的是解决了上面提出的问题吗
A:
只是解决了一部分情况。x和y是依赖关系,那么threadcontextclassloader的存在是能让程序正常运转,但是如果是关联关系(组合和聚合),以及继承。貌似他是起不到作用了。在类加载的时候就会查找父类或者是成员变量等等,只要变量是具体的类的名字,那么一定会去寻找这个类来完成加载。此时依然会有class not find的问题。只有能显示调用classloader的地方才有用(都显示调用classloader了,都是在操作object对象,没有具体类型,运行当然也是正常的)。
Q:
ibm的网站上为啥也没有举例说明,这种情况
A:
真的就是classloader的显示调用,没有其他附加效果,确实不用举例。