new的奥秘:Java中new关键字与类加载器

原创
开发 后端
"new"可以说是Java开发者最常用的关键字,我们使用new创建对象,使用new并通过类加载器来实例化任何我们需要的东西,但你是否深入了解过new在编译的瞬间都做了什么?

【51CTO独家特稿】在Java中使用new关键字创建对象变得很容易了,事实上,对这些事情你是不需要考虑的。需要访问一个文件吗?只需要创建一个新的File实例:new File(“build.properties”),对于大多数Java开发人员而言,这就是他们需要知道的一切,是不是很简单呢?!但当你使用了多个类加载器时,问题就不一样了。

这是我一年多来的第一反应,我就是不想知道这些东西,但奇怪的是,类加载器其实非常简单,大多数Java开发人员都知道编译时通过Java文件生成.class类文件,然后由Java虚拟机(JVM)载入这些编译后的类,这就是类加载器最基本的功能,但是和线程一样,问题不是理解他们做什么,而是让它们一起工作。

你听到过多少次“这是类加载器的问题”?我承认我听到过很多次,我自己也说过很多次。只要你的应用程序中不止一个类加载器,你不得不担心哪些类可以相互看到对方,这很容易成为一场噩梦。有关类加载器行为我将另外用一篇文章来说,现在我们还是回到new关键字吧。

当你创建一个新对象时,JVM首先加载类,当你使用new时这是透明的,问题是使用什么类加载器?以及为什么要使用它?
设想一个Grails情景,我们有一套基于Gant的构建系统,载入构建脚本并执行它们,我们以实例化一个Jetty服务器并启动它作为示例,对象的创建顺序是这样的:

Java中对象创建的顺序 
对象的创建顺序

事实上,上图展示的仅仅是一个简化的真实情况。

前3个类都在我们将要调用的生成类加载器的类路径下,因此是一次性将生成时需要用到的所有类全部加载了,但Jetty的Server类怎么加载呢?最重要的是要知道Server类必须要通过加载Grails Web应用程序相同的类加载器加载,虽然你可以将你自己的类加载器嵌入到服务器中,如果与加载Server的不一样,将会出现可怕的类加载器问题。

考虑到这一点,让我们看看如果RunApp脚本使用new创建服务器实例会发生什么:

  1. def server = new org.mortbay.jetty.Server()  
  2. ...  
  3. server.start() 

现在你应该问你自己“加载Server类该使用什么类加载器?”,这是一个关键问题,因为它决定了使用什么类加载器加载整个Web应用程序,也就决定了应用程序的运行时应该使用和依赖的类路径,在这种情况下,无论使用什么类加载器加载RunApp脚本,new操作符都会有效地授权给

  1. this.getClass().getClassLoader() 

我们的例子是什么意思呢?它意味着生成类加载器被用于加载Server类,因此也必须用于加载Web应用程序类,换句话说,所有应用程序的运行时依赖必须包括在生成类加载器中。你可能会问,这样会不会有问题?回答是有一个潜在的问题和一个实际的问题。
潜在的问题是类冲突,如果Web应用程序依赖一个已经存在于生成系统中不同版本的库会怎么样?如果所有Apache XML API库都在类路径下,这是一个特殊的问题,绝对会导致大破坏。

实际的问题是在类路径中JAR文件越多,JVM寻找类的时间就越长,这意味着启动时间就越长,这也是OSGi设计要解决的问题之一,为什么要将JAR放在生成类路径下呢?生成时本身是不需要它们的。

解决办法是确定类加载器的边界,使用映射实例化你的对象:

  1. def runtimeClassLoader = new URLClassLoader(...)  
  2. def server = runtimeClassLoader.loadClass("org.mortbay.jetty.Server").newInstance()  
  3. ...  
  4. server.start() 



 

责任编辑:佚名 来源: 51CTO.com
相关推荐

2009-08-21 14:16:35

C# New关键字

2023-03-24 08:01:27

Go语言内存

2024-06-04 17:02:38

newC#编程语言

2010-01-15 15:45:10

VB.NET New关

2012-03-13 14:41:41

JavaJVM

2024-03-28 10:40:43

javanew关键字

2009-06-25 10:33:53

StaticJava类

2020-08-10 08:00:13

JavaFinal关键字

2012-06-02 00:53:39

Javafinally

2022-05-06 08:32:40

Pythonwith代码

2024-04-08 11:35:34

C++static关键字

2009-09-28 11:34:49

Javascript

2023-11-19 22:52:42

2012-03-01 12:50:03

Java

2011-06-14 13:26:27

volatile

2024-02-23 18:04:37

C++const关键字

2009-11-26 19:24:54

PHP类CMS

2017-10-20 11:12:12

数据类型关键字对象

2021-10-20 07:36:03

Python构造方法

2023-10-26 08:12:37

Java变量类型
点赞
收藏

51CTO技术栈公众号