JiveJdon Community Forums
在线223人   首页   主题表   培训咨询   标签   查搜   注册    登陆 RSS
首页 » 论坛 » 设计模式、框架和架构
???en_US.forumThreadPrev.name??? 上一主题
google yahoo 365Key网摘 CSDN网摘 添加到百度搜藏 POCO网摘 新浪ViVi QQ网摘
???en_US.forumThreadNext.name??? 下一主题
1 2 3 4 Go 共有 55 回复(4页) 阅读208次
 发表新帖子   回复该主题贴
banq



发表文章: 10843
注册时间: 2002年08月03日
悄悄话
个人博客
在线? 当前离线
我要关注该作者发言 26人关注
Re: Java编程极限考验:ClassLoader类装载策略 2004年07月30日 11:31 收藏关注本主题 到本帖网址 加入本帖到收藏夹 请用鼠标选择需要回复的文字再点按本回复键 回复该主题
标签          
两位争论都有道理,对于初学者,一般应用,确实没必要搞这么复杂,但是我们实际开发中,发现这个思维有点大意了。

从现在回贴来看,还没有人碰到类似的感觉的人,我也只是从Exo代码的ServiceManager找到知音了啊,这个帖子就留在这里,估计几年后会有人跟贴的。
banq



发表文章: 10843
注册时间: 2002年08月03日
悄悄话
个人博客
在线? 当前离线
我要关注该作者发言 26人关注
Re: Java编程极限考验:ClassLoader类装载策略 2004年07月30日 12:26 收藏关注本主题 到本帖网址 加入本帖到收藏夹 请用鼠标选择需要回复的文字再点按本回复键 回复该主题
kewan观点因为回的是删除贴,也被不小心删除,补充如下:


不管是什么应用,我想首先需要搞清楚的是问题域。
在AppServer的设计过程中,要考虑到服务器的类装载,应用的类装载。二者共用和排斥的关系。有些类应用能看到,而不需服务器看到;有些服务器使用的类不能让应用看到;而有些类需要两者都看到(这时两者都可以各自装入,但为了节省内存和简单,共用最好)。这都是在问题域里思考的,不只是组装ClassLoader。如果光考虑ClassLoader,则是舍本求末了。
如果要自己写框架或服务器,设计ClassLoader确实要慎重。碰巧我做过一些服务器方面的工作,对这方面体会很深。不是ClassLoader本身的复杂性,而是问题域的复杂性。如果设计出的ClassLoader很复杂,说明你对问题域的理解又问题。而如果ClassLoader很简单,而且很灵活,那说明你走在正确的路上。所以,我反对把ClassLoader搞得很复杂,而强调理解问题域的需要。
kewan



发表文章: 46
注册时间: 2003年04月20日
悄悄话
个人博客
在线? 当前离线
我要关注该作者发言
Re: Java编程极限考验:ClassLoader类装载策略 2004年07月30日 14:45 收藏关注本主题 到本帖网址 加入本帖到收藏夹 请用鼠标选择需要回复的文字再点按本回复键 回复该主题
> 从现在回贴来看,还没有人碰到类似的感觉的人,我也只是从
> Exo代码的ServiceManager找到知音了啊
什么感觉?
原来没有看Banq在前面写的代码,原来是自己定义一个ClassLoader。我前面的回复就有一些文不对题了。Banq写的WrapperServlet好像有些错误:应该是继承HttpServlet吧。
如要在现有的框架下定义一个新的ClassLoader,那么原框架的ClassLoader的结构就需要搞清楚,Banq是对的。这样的话,部署应用时就不会出现莫名其妙的无法装入类的现象。
> 这个帖子就留在这里,估计几年后会有人跟贴的。
???
kewan



发表文章: 46
注册时间: 2003年04月20日
悄悄话
个人博客
在线? 当前离线
我要关注该作者发言
Re: Java编程极限考验:ClassLoader类装载策略 2004年07月30日 14:52 收藏关注本主题 到本帖网址 加入本帖到收藏夹 请用鼠标选择需要回复的文字再点按本回复键 回复该主题
>下面一段代码 是在Web容器中,实现Servlet类或Jsp类的动态装载,一
>般Servlet类部署到Web容器,是由Web容器监测Web.xml是否变化,
>以决定是否装载,这是非常被动的,使用下面代码通过ClassLoader可以
>在自己程序中主动实现装载:
自己装载Servlet不是一个好主意,这样就得自己维护这个Servlet的生命周期,得不偿失啊。呵呵
banq



发表文章: 10843
注册时间: 2002年08月03日
悄悄话
个人博客
在线? 当前离线
我要关注该作者发言 26人关注
Re: Java编程极限考验:ClassLoader类装载策略 2004年07月31日 15:49 收藏关注本主题 到本帖网址 加入本帖到收藏夹 请用鼠标选择需要回复的文字再点按本回复键 回复该主题
多谢kewan 指点,你提供了一个思路方向,我正在考虑。

那个Servlet是我举例,在我的设计中,主要也是类似Servlet这样有生命周期的框架,我的框架是要有生命周期的,才能在容器中反复部署调试使用。设计一个有生命周期的框架不是一件很容易的事情。

banq



发表文章: 10843
注册时间: 2002年08月03日
悄悄话
个人博客
在线? 当前离线
我要关注该作者发言 26人关注
Re: Java编程极限考验:ClassLoader类装载策略 2004年07月31日 17:40 收藏关注本主题 到本帖网址 加入本帖到收藏夹 请用鼠标选择需要回复的文字再点按本回复键 回复该主题
为了说明ClassLoader策略如此重要,以Spring框架中AopProxy为例:
这个AopProxy是所有代理实现的总接口,代理实现有jdk动态代理或cglib代理等。

public interface AopProxy {
/**
* Creates a new Proxy object for the given object, proxying
* the given interface. Uses the thread context class loader.
*/
public abstract Object getProxy();
/**
* Creates a new Proxy object for the given object, proxying
* the given interface. Uses the given class loader.
*/
public abstract Object getProxy(ClassLoader cl);
}

上面两个方法都是充分重视ClassLoader。
我们看看JdkDynamicAopProxy的一个实现是如何制定ClassLoader策略的:

public Object getProxy() {
return getProxy(Thread.currentThread().getContextClassLoader());
}

/**
* Create a new Proxy object for the given object, proxying
* the given interface. Uses the given class loader.
*/
public Object getProxy(ClassLoader cl) {
if (logger.isDebugEnabled()) {
logger.debug("Creating JDK dynamic proxy for [" + this.advised.getTargetSource().getTargetClass() + "]");
}
Class[] proxiedInterfaces = AopProxyUtils.completeProxiedInterfaces(this.advised);
return Proxy.newProxyInstance(cl, proxiedInterfaces, this);
}


注意这里策略是使用Thread.currentThread().getContextClassLoader(),而不是普通的Class.forName();

欢迎对这些有兴趣者一起谈论。

kewan



发表文章: 46
注册时间: 2003年04月20日
悄悄话
个人博客
在线? 当前离线
我要关注该作者发言
Re: Java编程极限考验:ClassLoader类装载策略 2004年08月01日 11:49 收藏关注本主题 到本帖网址 加入本帖到收藏夹 请用鼠标选择需要回复的文字再点按本回复键 回复该主题
Thread.currentThread().getContextClassLoader()指的是取得当前线程的ClassLoader,而Class.forName()其实也是使用当前线程的ClassLoader装入一个类,二者并没有本质的区别。
Class.forName()只是为了方便装入类而写的一个静态方法,不知为何Banq总是拿来和ClassLoader作比较,二者不是同一个级别的东西。
通过调用Thread.currentThread().setContextClassLoader(ClassLaoder load)方法,Class.forName()也可以装入其他ClassLoader范围内的类。
如果还不明白的话,去看看Class.forName()的源代码,就一清二楚了。
kewan



发表文章: 46
注册时间: 2003年04月20日
悄悄话
个人博客
在线? 当前离线
我要关注该作者发言
Re: Java编程极限考验:ClassLoader类装载策略 2004年08月01日 11:58 收藏关注本主题 到本帖网址 加入本帖到收藏夹 请用鼠标选择需要回复的文字再点按本回复键 回复该主题
在AopProxy例子中,使用两个方法取得Proxy,第一个时使用当前线程的ClassLoader,另一个是使用指定的ClassLoader,这两个方法是一致的,所以无参数的那个有参数的那个来实现。在newProxyInstance的实现里,使用Class.forName()装入也是可以的。不相信就自己修改一下,看能不能行,呵呵。
banq



发表文章: 10843
注册时间: 2002年08月03日
悄悄话
个人博客
在线? 当前离线
我要关注该作者发言 26人关注
Re: Java编程极限考验:ClassLoader类装载策略 2004年08月02日 09:00 收藏关注本主题 到本帖网址 加入本帖到收藏夹 请用鼠标选择需要回复的文字再点按本回复键 回复该主题
>使用Class.forName()装入也是可以的
多谢kewan,我更改了之后第一次可以运行,第二次部署就不行了,我已经做过明显的实验对比。

写在这里意在提醒大家,注意这个区别,特别是碰到很头疼的问题时,还有EJB打包时,也存在这个问题,甚至发生无法部署的问题。

希望有以上经验的人来谈谈自己的实践感受。
kewan



发表文章: 46
注册时间: 2003年04月20日
悄悄话
个人博客
在线? 当前离线
我要关注该作者发言
Re: Java编程极限考验:ClassLoader类装载策略 2004年08月02日 13:44 收藏关注本主题 到本帖网址 加入本帖到收藏夹 请用鼠标选择需要回复的文字再点按本回复键 回复该主题
>我更改了之后第一次可以运行,第二次部署就不行了
??? 为何第二次就不行了?

另外,Class.forName()使用的ClassLoader实际上是Lancher的AppClassloader,希望这条信息能有帮助。
banq



发表文章: 10843
注册时间: 2002年08月03日
悄悄话
个人博客
在线? 当前离线
我要关注该作者发言 26人关注
Re: Java编程极限考验:ClassLoader类装载策略 2004年08月02日 15:49 收藏关注本主题 到本帖网址 加入本帖到收藏夹 请用鼠标选择需要回复的文字再点按本回复键 回复该主题
>为何第二次就不行了?
我更换了Thread.XX就可以运行,说明这两者在某些情况下是有区别的。
我本想将它总结出规律,目前我只能得出,如果你做的是框架等非最终层的软件,那么最好不用CLass.ForName, 好好地留心注意处理你的框架的CLassLoader策略。
kewan



发表文章: 46
注册时间: 2003年04月20日
悄悄话
个人博客
在线? 当前离线
我要关注该作者发言
Re: Java编程极限考验:ClassLoader类装载策略 2004年08月02日 19:08 收藏关注本主题 到本帖网址 加入本帖到收藏夹 请用鼠标选择需要回复的文字再点按本回复键 回复该主题
>好好地留心注意处理你的框架的CLassLoader策略
呵呵,现在和我的观点相同了。

>我更换了Thread.XX就可以运行,说明这两者在某些情况下是有区别的。
当然有区别,但本质上是一样的。

>那么最好不用CLass.ForName
其实我一般不用Class.forName(),只是对楼上的各位总是抬出Class.forName感到有些不解,所以就发了这些议论。既然大家观点一致,就没有什么好说得了,呵呵
raimundo



发表文章:
注册时间: 2004年01月31日
悄悄话
个人博客
在线? 当前离线
我要关注该作者发言
Re: Java编程极限考验:ClassLoader类装载策略 2004年09月14日 21:05 收藏关注本主题 到本帖网址 加入本帖到收藏夹 请用鼠标选择需要回复的文字再点按本回复键 回复该主题
Class.forName有两个签名Class.forName(String)和Class.forName(String, boolean, ClassLoader),最终都是调用内部native方法forName0,第一个签名实现是return forName0(className, true, ClassLoader.getCallerClassLoader()),第二个稍微复杂一些,但是大概认为是在当指定loader==null的时候使用ClassLoader.getCallerClassLoader().
再看ClassLoader.getCallerClassLoader()怎么实现,很简单通过一个native方法得到caller class然后getClassLoader()
现在结论很简单了,当caller class不是由current thread的context ClassLoader load的时候,两者的结果会不一致,但是大部分情况下是一致的。
这是一个很简单的问题,banq只要看看source,根本不用扯到具体的应用里,还弄出exo这个东西,exo里用currentThread的context classLoader是为了灵活,由Thread控制,而不需要显示的传入一个ClassLoader而已.
而且ClassLoader是一个很简单的问题,根本谈不上什么深奥,只不过大家接触的少以为很神秘罢了,banq不要自己理解了个东西,就说出什么极限考验云云,容易误导初学者.
sunsonbaby



发表文章:
注册时间: 2004年03月29日
悄悄话
个人博客
在线? 当前离线
我要关注该作者发言
Re: Java编程极限考验:ClassLoader类装载策略 2004年09月23日 12:28 收藏关注本主题 到本帖网址 加入本帖到收藏夹 请用鼠标选择需要回复的文字再点按本回复键 回复该主题
very good.
banq



发表文章: 10843
注册时间: 2002年08月03日
悄悄话
个人博客
在线? 当前离线
我要关注该作者发言 26人关注
Re: Java编程极限考验:ClassLoader类装载策略 2004年09月24日 09:19 收藏关注本主题 到本帖网址 加入本帖到收藏夹 请用鼠标选择需要回复的文字再点按本回复键 回复该主题
多谢 raimundo 解释,在嵌套ClassLoader环境中就没有这么简单了,掌握在嵌套ClassLoader环境中使用策略应该是Java高级应用,这只是经验之谈。
标签          
共有 55 回复(4页) Go 1 2 3 4
???en_US.forumThreadPrev.name??? 上一主题
  Go back to the topic 返回本主题   Go back to the topic listing返回主题列表    返回页首返回页首
???en_US.forumThreadNext.name??? 下一主题
正在读取,请等待...
查询本论坛内 回复超过的热门帖子
标题
 
粗体: [b]文本[/b] 斜体: [i]文本[/i] 下划线 [u]文本[/u] 插入网上的图片 [img]http://wwww.xxxx.com/img.ext[/img] 插入代码 [code]程序代码[/code]  插入url链接 [url]http://url[/url] / [url=http://url]URL加下滑线[/url] 上传图片 word文档 Txt等附件
内容
  提交时自动拷贝以上内容到剪贴板 Ctrl-V可取出;提问题前先查询标签列表

使用帮助 手机阅读 add to google add to yahoo
解惑之道在J道 ,打造中国最具影响力的的软件架构社区 推荐FireFox或Chrome快速浏览本站
OpenSource JIVEJDON Powered by JdonFramework Code © 2002-09 jdon.com
anti spam