【问题标题】:Java Class Loaders [closed]Java 类加载器 [关闭]
【发布时间】:2010-10-07 02:39:33
【问题描述】:

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

  • 为什么开发人员要编写自定义类加载器,为什么不调用 Bootstrap 类加载器来调用您的自定义类?自定义类加载器需要什么?

  • 为什么有这么多种类加载器? eg: Bootsrap, Comman, Catalina 类加载器等,

    提前致谢。

【问题讨论】:

    标签: java classloader dynamic-class-loaders


    【解决方案1】:

    我发现以下创建自定义类加载器的正当理由:

    1. 您希望从非常规来源加载一个类(例如,一个类的字节码存储在数据库中,通过网络或carried as 0 and 1s by pidgeons - MessengerPidgeonClassLoader)。针对此类情况,API 中已经有一些 ClassLoader 实现,例如 URLClassLoader

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

    3. 您需要对字节码进行一些修改。也许字节码是加密的,你会即时解密它(Not that it helps, really, but has been tried)。也许您想“修补”动态加载的类(A la JDO 字节码增强)。

    如果您需要从内存中卸载类或加载类而不是在运行时更改其定义,则需要使用与系统类加载器不同的类加载器。例如,一个典型的情况是应用程序从 XML 文件动态生成一个类,然后尝试重新加载该类。一旦一个类在系统类加载器中,就没有办法卸载它并有一个新的定义。

    【讨论】:

    • 不错的答案,但 pidgeons 保证加 1​​ :)
    • Avian Carriers 上的 IP 数据报是有史以来最好的 RFC :) 猜猜看,它也已经在现实生活中进行了测试! notes.co.il/benbasat/5240.asp
    • 问题结束后,我将添加与您的第 3 点相关的评论:在进行第一轮测试时热交换类 - 如果系统重启时间很长并且超出您的直接影响,则非常相关。可以在适当的情况下完成 - 虽然当然通常不适合生产系统。
    【解决方案2】:

    类加载器的一个常见用途是隔离 JAR。如果您有一个使用插件的应用程序(EclipseMaven 2),那么您可能会遇到这种情况:插件 X 需要 jar A 版本为 1.0,而插件 Y 需要相同的 jar 但版本为 2.0。不过,X 不支持 2.0 版。

    如果您有类加载器,则可以创建类的分区(想想由薄桥连接的孤立岛屿;这些桥就是类加载器)。这样,类加载器可以控制每个插件可以看到的内容。

    当插件 X 实例化具有静态字段的类 Foo 时,这没有问题,并且不会与插件 Y 中的“相同”类混淆,因为每个类加载器实际上都会创建自己的类实例福。然后,您在内存中有两个类,其中 cl1.getName().equals(cl2.getName())truecl1.equals(cl2) 不是。这意味着 cl1 的实例与 cl2 的实例不兼容。这可能会导致奇怪的ClassCastExceptionsorg.project.Foo 不能分配给org.project.Foo

    就像偏远岛屿一样,这两个班级不知道另一个班级的存在。想想在不同岛屿上出生然后长大的克隆人。从 VM 的角度来看,没有问题,因为 Class 类型的实例的处理方式与任何其他对象一样:可以有多个。您认为其中一些是“相同的”对于 VM 来说并不重要。

    此模式的另一个用途是您可以摆脱以这种方式加载的类:只要确保没有人拥有指向从类加载器加载的类创建的任何对象的指针,然后也忘记类加载器。在GC 的下一次运行中,由该类加载器加载的所有类都将从内存中删除。这允许您“重新加载”您的应用程序,而无需重新启动整个 VM。

    【讨论】:

    • 很好的比喻,岛国! +1
    【解决方案3】:

    Java 类加载器的另一个好链接 - Java classloaders

    【讨论】:

      【解决方案4】:

      我在过去写过一些关于使用授权后类加载器的博客:

      【讨论】:

        【解决方案5】:

        在这种情况下,您不能超越原始来源。如果您真的想要内部涂料,硬核,请阅读the relevant bits of the Java Virtual Machine Specification

        【讨论】:

          【解决方案6】:

          您很少需要创建自己的 ClassLoader。通常,如果您需要,您应该已经非常了解 ClassLoader 的作用。

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

          话虽如此,我还看到为处理密码学的应用程序创建了一个 ClassLoader。这样,每次您创建 java.netSocket 或某种文件/流对象时,它不会使用 JVM 版本,而是使用它们自己特殊的自定义构建类。通过这种方式,他们可以保证所有信息都已加密并且没有开发人员错误。

          但这不是很常见。您无需创建自己的自定义 ClassLoader 即可完成整个 Java 职业生涯。其实如果你需要创建一个,你真的应该问是否有必要。

          【讨论】:

            【解决方案7】:

            一个例子:

            Tomcat 使用定制的 WebAppClassloader 从不同的 Web 应用程序中加载和隔离类/jar。

            【讨论】:

              【解决方案8】:

              为什么开发人员要编写自定义类加载器,为什么不调用 Bootstrap 类加载器来调用您的自定义类?自定义类加载器需要什么?

              根据应用程序,开发人员可能会覆盖或完全替换类加载机制以满足他们的需求。

              例如,我使用了一个应用程序,其类是从 LDAP 加载的:S

              其他应用需要独立的类管理(像大多数支持热部署的应用服务器)

              关于资源,网络上有大量无法列出的资源。

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 1970-01-01
                • 2012-11-08
                • 2013-02-28
                • 2012-11-27
                • 1970-01-01
                • 1970-01-01
                • 2013-05-06
                • 2012-11-01
                相关资源
                最近更新 更多