Java类加载器

25

有没有人能指点我一个好的资源或者解释一下类加载器背后的概念?我在类加载器方面找到了以下的资源http://www.onjava.com/lpt/a/5586,但还是没有帮助。以下问题可能看起来很傻,但尝试回答它们总是让我感到困惑。

  • 为什么开发人员要编写自定义类加载器?为什么不调用启动类加载器来调用您的自定义类?定义自定义类加载器的必要性是什么?

  • 为什么有这么多种类的类加载器?例如:引导、通用、Catalina 类加载器等。

    先谢谢了。

8个回答

46
我找到了以下有效的原因来创建自定义类加载器:
  1. 你想从非传统来源加载类(例如,一个类的字节码存储在数据库中、通过网络或由鸽子携带为0和1 - MessengerPidgeonClassLoader)。已经有一些API中的ClassLoader实现用于这种情况,例如URLClassLoader

  2. 您需要定义不同的层次结构来加载类。ClassLoader的默认实现首先将搜索委托给父级,然后尝试自己加载类。也许您想要一个不同的层次结构。这就是OSGI和Eclipse拥有自己的ClassLoader的原因,因为Manifest .MF文件定义了各种奇怪的层次结构路径(例如buddy-classloading)。所有Eclipse类加载器都实现BundleClassLoader接口,并具有一些额外的代码以在Eclipse插件中查找资源。

  3. 您需要对字节码进行一些修改。也许字节码被加密,你将在运行时解密它(虽然这并没有什么帮助,但已经尝试过)。也许你想“修补”在运行时加载的类(就像JDO字节码增强一样)。

如果需要从内存中卸载类或加载可能在运行时更改其定义的类,则需要使用不同于系统类加载器的类加载器。典型情况是应用程序从XML文件动态生成类,然后尝试重新加载此类。一旦类位于系统类加载器中,就无法卸载它并获得新的定义。


好的回答,但鸽子保证加一 :) - ShuggyCoUk
2
IP Datagrams on Avian Carriers是有史以来最好的RFC :) 而且你猜怎么着,它还在现实生活中得到了测试!http://www.notes.co.il/benbasat/5240.asp - Esko
由于问题已关闭,我将添加一条评论与您的第3点相关:在进行第一轮测试时热交换类——如果系统重新启动时间很长并且超出您的直接影响范围,则非常相关。可以通过适当的注意来完成——尽管通常不适用于生产系统。 - nsandersen

32
常见的类加载器用法是隔离一个JAR文件。如果你有一个使用插件(EclipseMaven 2)的应用程序,那么可能会出现这种情况:插件X需要版本1.0的A JAR文件,而插件Y需要相同的JAR文件但版本为2.0。然而,X不能使用版本2.0。
如果您有类加载器,则可以创建类的分区(想象一下由薄桥连接的隔离岛屿;这些桥梁就是类加载器)。这样,类加载器可以控制每个插件可以看到什么。
当插件X实例化一个具有静态字段的类Foo时,这不是问题,因为与插件Y中的“相同”类不会混淆,因为实际上每个类加载器都将创建其自己的类Foo实例。然后在内存中有两个类,其中cl1.getName().equals(cl2.getName())true,但 cl1.equals(cl2) 不是。这意味着cl1的实例不能赋值给cl2的实例。这可能导致奇怪的ClassCastExceptions,其显示无法将org.project.Foo分配给org.project.Foo
就像遥远的岛屿一样,这两个类并不知道彼此的存在。想象一下人类克隆体,在不同的岛屿上出生并成长。从虚拟机的角度来看,没有问题,因为类的实例被处理得像任何其他对象一样:可以有多个实例。你认为其中一些是“相同的”并不影响虚拟机。
这种模式的另一个用途是可以摆脱以这种方式加载的类:只需确保没有人有指向从类加载器创建的任何对象的指针,然后忘记类加载器。在下一次GC运行时,该类加载器加载的所有类都将从内存中删除。这使您可以“重新加载”应用程序,而无需重新启动整个虚拟机。

1
不错的比喻,那个岛屿的!+1 - Mario Ortegón

3

2

2

1
一个例子:
Tomcat使用定制的WebAppClassloader来加载和隔离不同Web应用程序中的类/ JAR。

1

你很少需要创建自己的ClassLoader。一般来说,如果你需要创建一个,你应该已经非常了解ClassLoader的作用。

换句话说,如果你问为什么需要创建自己的ClassLoader,那么你就不需要创建一个;)

话虽如此,我也见过为处理加密技术的应用程序创建ClassLoader的情况。这样,每次创建java.netSocket或某种文件/流对象时,它们会使用自己特殊构建的类,而不是使用JVM版本。这样他们可以保证所有信息都被加密,没有开发人员错误。

但这并不常见。你可以在整个Java职业生涯中从未需要创建自己的自定义ClassLoader。实际上,如果你需要创建一个,你应该真正考虑是否有必要。


0
开发人员为什么要编写自定义类加载器,而不是调用引导类加载器来调用你的自定义类?定义自定义类加载器的必要性是什么?
根据应用程序的不同,开发人员可能会覆盖或完全替换类加载机制以适应其需求。
例如,我曾经使用过一款从LDAP中加载类的应用程序:S
其他应用程序需要独立的类管理(如支持热部署的大多数应用程序服务器)
至于资源,在网络上有很多资源,无法一一列举。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接