posts - 80,comments - 749,trackbacks - 2

Flier Lu问到CLR LoaderJava Class Loader有什么不一样。要回答这个问题不容易,因为我对Java一窍不通。但既然问题提出来了,打肿脸来充胖子也得回答啊。

 

于是今天下午我在google上逛了一圈,找了些关于Java Class Loader的文章看了看。我的结论是,和Java Class Loader类似的东东,在CLR里是不存在的。

 

简单的说,CLR里不存在一个类似于Java.Lang.ClassLoader的东西。所以你无法实现你自己的CLR LoaderCLR里只有一个Loader,那就是CLR Loader。当然,CLR提供了自己独特的方式让你做动态装载。你所拥有的自由度是远比Java要大得多。

 

下面是具体分析。

 

我对Java Class Loader的理解主要是从这两篇文章里来的。

“Inside Class Loader” by Andeas Schaefer (http://www.onjava.com/lpt/a/4337) “The basics of Java Class Loaders” by Chuck McManis (http://www.javaworld.com/javaworld/jw-10-1996/jw-10-indepth_p.html)。我看了看JVM Spec。但是我觉得不如上面两篇文章清楚。

 

先说Java里的Type吧。Java里的Type就是Class Class就是Namespace + class name.  Class通过Class Loader来装载的。System Class Loader缺省的话只在CLASSPATH中寻找Class。如果你要在CLASSPATH之外转载Class的话,你就需要自己的Class Loader。如果两个Class有相同的名字,并且在同一个Class Loader里,那么它们就被JVM认为是相同的,可以互相赋值。如果有一个不一样的话,它们就被认为是不一样的。互相赋值会发生ClassCaseException。换句话说,Class name + Class Loader是一个Type的独特的ID

 

Java的这个模型有很多问题。首先它把Class name做为TypeID。两个Class如果有同样的名字,但是实际内容不一样的话,如果它们被同一个Class Loader装载,JVM会认为它们是同一个 Type。这个太搞笑了。结果就是Class Loader必须要有一些特别的办法来管理Class name。一般的办法是加一个前缀,比如说ClassURL。如果Namespace管理不好的话,很容易就是安全漏洞。这是为什么JVM Spec里提到Class Loader必须要让Parent Class Loader先搜索Class,再自己寻找。而且Class loader必须要保存Class resolution的结果,这样下次Class resolution的时候,Class loader会返回同样的结果。Java Class Loader有太多的限制,同时又有太多的责任。

 

另一个问题是共享问题。如果同一个Class被两个不同的Class Loader装载的话,JVM认为这两个Class不是同一个Type,不能互相赋值。结果就是Class无法共享。被不同Class Loader装载的Class无法直接对话。直接对话会产生linkage错误。它们只能间接对话,比如通过Interface,或者共同的Base Class

 

还有一个问题是Versioning。因为JavaType里只有名字,所以当你看到一个Type的时候,你无法知道它是第一版,还是第二版。所以如果你需要第二版,但是Class loader给你装载了第一版的时候,祈祷吧。也许上帝能救你。

 

现在回过头来看看CLR的模型。CLRType包括两部分:Class name + Assembly NameClass name是和 JavaType类似的东西,就是namespaceAssemblyJava没有的东西。Assembly Name的属性包括Name, Version, Culture, PublicKey(Token) 如果两个Assembly有一个属性不一样,那么它们就认为是不一样的。两个Type如果有同样的Class name,但是Assembly Name不一样的话,它们也认为是不一样的。

 

CLRType引用总是包括Class name Assembly Name的。所以CLR在寻找一个Type的时候,主要是寻找Assembly。找到了Assembly之后,CLR看看这个Assembly里有没有这个Class。有的话就万事大吉,没有的话就是TypeLoadException

 

CLR区别Type主要靠AssemblyAssemblyPublicKey(Token)。别人无法冒充你。所以象Java里的namespace的问题就不存在了。Assembly有自己的Version。你要第二版的时候CLR不会装载第一版给你。所以象Java Class Loader那样的限制,责任和问题都不存在了。从这个角度上讲,这正是为什么CLR里没有象Java Class Loader那样的东西。

 

但并不是说你就不能动态装载了,而是说你动态装载的时候就不用考虑那些垃圾了。

 

关于共享的问题,因为没有了你自己的Class loader,所以任何Type都可以直接对话。同样的Type也不会因为Class Loader不一样而被认为不一样。

 

CLR Loader有自己的规则怎么寻找Assembly。它先看GAC,再看你的程序目录。都没有的话它还有一个AssemblyResolveEvent去问你,看你能不能提供。如果你要动态装载的话,你有Assembly.Load, Assembly.LoadFrom, Assembly.LoadFile, Assembly.Load(byte[])。你可以提供privateBin,你也可以提供codebase hint。你还能有policy。总之,你想从哪找,就可以去哪找。细节问题我就不多说了。你可以去看MSDNSuzanneBlogAlanBlog,和我的英文Blog.

 

结论,CLR Loader远比Java Class Loader要Secure, Powerful and Flexible

posted on 2005-03-28 11:34 Brian Sun 阅读(686) 评论(1)  编辑  收藏 所属分类: 软件转贴

FeedBack:
# re: CLR Loader and Java Class Loader Compared[转][未登录]
2009-06-06 19:06 | test
简直是一派胡言,不懂就不要写文章  回复  更多评论
  

只有注册用户登录后才能发表评论。


网站导航: