class.forname()
和thread.currentthread().getcontextclassloader())
是否一样?
在很多文章中,都认为两者是一致的,如java研究组织中一篇文章,被我从google搜索到的:
http://www.javaresearch.org/article/showarticle.jsp?column=31&thread=10178
文中说"这个方法可以用class.forname()代替",在一般简单情况是可以替代,但实际上有时候是不能替代的。
classloader存在下面问题:
在一个jvm中可能存在多个classloader,每个classloader拥有自己的namespace。一个classloader只能拥有一个class对象类型的实例,但是不同的classloader可能拥有相同的class对象实例,这时可能产生致命的问题。如classloadera,装载了类a的类型实例a1,而classloaderb,也装载了类a的对象实例a2。逻辑上讲a1=a2,但是由于a1和a2来自于不同的classloader,它们实际上是完全不同的,如果a中定义了一个静态变量c,则c在不同的classloader中的值是不同的。
因此,研究jboss的classloader策略,对于更好地实现ejb组件拼装是用好处的,因为,一个项目中可能要用其他项目的ejb组件,如何实现运行时ejb组件共享,如何实现ejb组件打包是很重要的。
为了说明classloader对于复杂架构是至重关键,列举开源portal产品exo中servivesmanager类内容。
该类是exo利用picocontainer实现功能性service javabeans初始化,在将那些service性质的javabeans加载到pico中时,需要使用到classloader,
exo专门设立一个servicecontext类:
public class servicecontext { private classloader cl; //包含classloader信息 private services services; public servicecontext(classloader cl, services services) { this.cl = cl; this.services = services; } public classloader getcl() { return cl; } public services getservices() { return services; }}
在servicesmanager中,有:
private classloader updatedclassloader;
它的初始值是:
thread.currentthread().getcontextclassloader();
如果,这里写class.forname 那么简单,那么你头疼去吧。
但是这样不够:
在addservice方法中,根据加入的不同servicecontext实现类装载:
public void addservice(servicecontext context) { services servicestoadd = context.getservices(); string name = servicestoadd.getname(); urlclassloader cl = null; if(context.getcl() instanceof urlclassloader) { cl = (urlclassloader) context.getcl(); } else { cl = urlclassloader.newinstance(new url[]{}, context.getcl()); } updatedclassloader = new urlclassloader(cl.geturls(), updatedclassloader); synchronized (servicescontext) { servicescontext.put(name, context); reloadcontainer(); } }
其实向picocontainer中加入一个服务很简单,上述方法的主要代码是处理classloader,考虑到classloader有嵌套关系,上述代码小心使用这个service服务的父classloader,使用父classloader装载服务service。
文章整理:西部数码--专业提供域名注册、虚拟主机服务
http://www.west263.com
以上信息与文章正文是不可分割的一部分,如果您要转载本文章,请保留以上信息,谢谢!


