Java中new关键字与类加载器原理.docVIP

  1. 1、原创力文档(book118)网站文档一经付费(服务费),不意味着购买了该文档的版权,仅供个人/单位学习、研究之用,不得用于商业用途,未经授权,严禁复制、发行、汇编、翻译或者网络传播等,侵权必究。。
  2. 2、本站所有内容均由合作方或网友上传,本站不对文档的完整性、权威性及其观点立场正确性做任何保证或承诺!文档内容仅供研究参考,付费前请自行鉴别。如您付费,意味着您自己接受本站规则且自行承担风险,本站不退款、不进行额外附加服务;查看《如何避免下载的几个坑》。如果您已付费下载过本站文档,您可以点击 这里二次下载
  3. 3、如文档侵犯商业秘密、侵犯著作权、侵犯人身权等,请点击“版权申诉”(推荐),也可以打举报电话:400-050-0827(电话支持时间:9:00-18:30)。
  4. 4、该文档为VIP文档,如果想要下载,成为VIP会员后,下载免费。
  5. 5、成为VIP后,下载本文档将扣除1次下载权益。下载后,不支持退款、换文档。如有疑问请联系我们
  6. 6、成为VIP后,您将拥有八大权益,权益包括:VIP文档下载权益、阅读免打扰、文档格式转换、高级专利检索、专属身份标志、高级客服、多端互通、版权登记。
  7. 7、VIP文档为合作方或网友上传,每下载1次, 网站将根据用户上传文档的质量评分、类型等,对文档贡献者给予高额补贴、流量扶持。如果你也想贡献VIP文档。上传文档
查看更多
Java中new关键字与类加载器原理

Java中new关键字与类加载器原理 在Java中使用new关键字创建对象变得很容易了,事实上,对这些事情你是不需要考虑的。需要访问一个文件吗?只需要创建一个新的File实例:new File “build.properties” ,对于大多数Java开发人员而言,这就是他们需要知道的一切,是不是很简单呢?!但当你使用了多个类加载器时,问题就不一样了。 这是我一年多来的第一反应,我就是不想知道这些东西,但奇怪的是,类加载器其实非常简单,大多数Java开发人员都知道编译时通过Java文件生成.class类文件,然后由Java虚拟机(JVM)载入这些编译后的类,这就是类加载器最基本的功能,但是和线程一样,问题不是理解他们做什么,而是让它们一起工作。 你听到过多少次“这是类加载器的问题”?我承认我听到过很多次,我自己也说过很多次。只要你的应用程序中不止一个类加载器,你不得不担心哪些类可以相互看到对方,这很容易成为一场噩梦。有关类加载器行为我将另外用一篇文章来说,现在我们还是回到new关键字吧。 当你创建一个新对象时,JVM首先加载类,当你使用new时这是透明的,问题是使用什么类加载器?以及为什么要使用它? 设想一个Grails情景,我们有一套基于Gant的构建系统,载入构建脚本并执行它们,我们以实例化一个Jetty服务器并启动它作为示例,对象的创建顺序是这样的: ? 对象的创建顺序 事实上,上图展示的仅仅是一个简化的真实情况。 前3个类都在我们将要调用的生成类加载器的类路径下,因此是一次性将生成时需要用到的所有类全部加载了,但Jetty的Server类怎么加载呢?最重要的是要知道Server类必须要通过加载Grails Web应用程序相同的类加载器加载,虽然你可以将你自己的类加载器嵌入到服务器中,如果与加载Server的不一样,将会出现可怕的类加载器问题。 考虑到这一点,让我们看看如果RunApp脚本使用new创建服务器实例会发生什么: def?server? ?new?org.mortbay.jetty.Server ... ? server.start 现在你应该问你自己“加载Server类该使用什么类加载器?”,这是一个关键问题,因为它决定了使用什么类加载器加载整个Web应用程序,也就决定了应用程序的运行时应该使用和依赖的类路径,在这种情况下,无论使用什么类加载器加载RunApp脚本,new操作符都会有效地授权给 this.getClass .getClassLoader 我们的例子是什么意思呢?它意味着生成类加载器被用于加载Server类,因此也必须用于加载Web应用程序类,换句话说,所有应用程序的运行时依赖必须包括在生成类加载器中。你可能会问,这样会不会有问题?回答是有一个潜在的问题和一个实际的问题。 潜在的问题是类冲突,如果Web应用程序依赖一个已经存在于生成系统中不同版本的库会怎么样?如果所有Apache XML API库都在类路径下,这是一个特殊的问题,绝对会导致大破坏。 实际的问题是在类路径中JAR文件越多,JVM寻找类的时间就越长,这意味着启动时间就越长,这也是OSGi设计要解决的问题之一,为什么要将JAR放在生成类路径下呢?生成时本身是不需要它们的。 解决办法是确定类加载器的边界,使用映射实例化你的对象: def?runtimeClassLoader? ?new?URLClassLoader ... def?server? ?runtimeClassLoader.loadClass org.mortbay.jetty.Server .newInstance ... ? server.start 在Groovy中这是很容易办到的,因为start 方法是在运行时评估的,但Java需要知道编译时类型,你不能这样做: ? ClassLoader?runtimeClassLoader? ?new?URLClassLoader ... Server?server? ? Server runtimeClassLoader.loadClass org.mortbay.jetty.Server .newInstance ... ? server.start 因为在第2行你会得到一个ClassCastException,服务器的声明性类型是由this.getClass .getClassLoader 加载的,但new实例是由另一个不同的类加载器加载的,不同的类加载器意味着不同的类,因此你必须使用映射调用方法和访问你需要的字段。 ? 正如你所看到的,正常情况下,你不要考虑new操作符,但只要你要处理多个类加载器,你必须要仔细了解它们的行为,关键是制定出合适的类加载器边界,然后使用映射来加载和实例化在那些边界上的类。听起来好

文档评论(0)

peain + 关注
实名认证
文档贡献者

该用户很懒,什么也没介绍

1亿VIP精品文档

相关文档