Java编程极限考验:ClassLoader类装载策略

本文指出Java编程中Classloader机制的掌握和运用是极限考验,特别是在复杂系统环境。探讨了Class.forName()和Thread.currentThread().getContextClassLoader()的差异,分析了ClassLoader存在的问题,还阐述了研究JBoss的ClassLoader策略对EJB组件拼装的好处,并以开源Portal产品Exo为例说明其重要性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

个人认为,Java编程中极限考验是Classloader机制的掌握和灵活运用,特别是在复杂的系统,如存在动态类装载,Reflect,EJB,AOP等环境。

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实现功能性ServiceJavaBeans初始化,在将那些Service性质的JavaBeans加载到pico中时,需要使用到Classloader,
Exo专门设立一个ServiceContext类:




publicclassServiceContext{privateClassLoadercl;//包含Classloader信息privateServicesservices;publicServiceContext(ClassLoadercl,Servicesservices){this.cl=cl;this.services=services;}publicClassLoadergetCl(){returncl;}publicServicesgetServices(){returnservices;}}


在ServicesManager中,有:
privateClassLoaderupdatedClassLoader;

它的初始值是:
Thread.currentThread().getContextClassLoader();

如果,这里写Class.forName 那么简单,那么你头疼去吧。

但是这样不够:
在addService方法中,根据加入的不同ServiceContext实现类装载:



publicvoidaddService(ServiceContextcontext){ServicesservicesToAdd=context.getServices();Stringname=servicesToAdd.getName();URLClassLoadercl=null;if(context.getCl()instanceofURLClassLoader){cl=(URLClassLoader)context.getCl();}else{cl=URLClassLoader.newInstance(newURL[]{},context.getCl());}updatedClassLoader=newURLClassLoader(cl.getURLs(),updatedClassLoader);synchronized(servicesContext){servicesContext.put(name,context);reloadContainer();}}


其实向Picocontainer中加入一个服务很简单,上述方法的主要代码是处理Classloader,考虑到Classloader有嵌套关系,上述代码小心使用这个Service服务的父Classloader,使用父Classloader装载服务Service。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值