【问题标题】:What is the need of different class loaders in javajava中不同的类加载器需要什么
【发布时间】:2013-12-14 02:52:06
【问题描述】:

我读过java中有不同的类加载器,一个是原始类加载器,也有自定义类加载器,所以我想了解为什么原始类加载器不能为java中的所有类提供服务? 为什么需要其他类加载器?

【问题讨论】:

标签: java class classloader


【解决方案1】:

一个原因是安全性。例如,默认(包私有)可见性级别只允许访问来自同一包的类,并由同一类加载器加载。这使得恶意代码更难访问您的内部 API。

参考文献:

【讨论】:

    【解决方案2】:

    类加载器的类型:

    1. 引导带类加载器/前置类加载器
    2. 扩展类加载器
    3. 应用程序类加载器/系统类加载器

    Boot Strap Class loader:负责加载核心 JAVA API 类,即 rt.jar 中存在的类

    rt.jar 的位置 -> jdk/jre/lib/rt.jar 这也称为引导类路径。

    引导类加载器从引导类路径加载类。 Bootstrap 是用 C 或 C++ 等原生语言实现的,而不是用 JAVA 实现的。

    扩展类加载器:从扩展类路径加载类,即 jdk/jre/lib/ext/*.jar

    扩展类加载器是 BootStrapClassLoader 的子类,它是用 JAVA 实现的。

    对应的JAVA类是sun.misc.Launcher$ExtClassLoader.class

    Application Class Loader: Extension 类加载器的子类。应用程序类加载器从应用程序类路径加载类。它在内部使用环境类路径。

    它在 JAVA 中实现。对应的JAVA Classes是sun.miscLauncher$AppClassLoader.class

    类加载器遵循委托层次原则。每当 JVM 遇到一个特定的类时,它首先会检查 .class 文件是否已经加载到哪里。如果它已经加载到方法区域,那么 JVM 将考虑加载的类,如果没有,JVM 请求 Class Loader Subsystem 加载特定的类。类加载器子系统将请求移交给应用程序类加载器,它将请求委托给扩展类加载器,然后委托给引导类加载器搜索引导类路径,如果没有找到,扩展类加载器搜索扩展类路径,如果找不到则应用程序类laoder 搜索 Application Class 路径,如果仍然找不到该类,则会出现 ClassNotFoundException 或 NoClassDefFoundError。

    【讨论】:

      【解决方案3】:

      在许多实际情况下,您需要系统类加载器提供的功能之外的功能:

      1. 您可以授予对自定义类源的访问权限(例如,通过 http)
      2. 您可以缓存数据块(例如,'如果需要这个类,那么让我预加载这些其他类')
      3. 您可以合并安全协议来阻止加载某些类
      4. 您可以保留使用的类的统计信息,以便以后优化您的 jar 档案
      5. 您可以在加载类时执行字节码转换(“加载时编织”),例如,修改符合特定模式的类。面向方面的编程实现可以使用这种技术。

      最后一点特别强大(也是我使用它们的主要原因)。由于 Java 字节码是跨平台通用的,因此您可以使用它来检测任何系统上的类:测量调用了哪些方法、抑制安全关键调用、将 System.out 访问转移到您自己的自定义日志记录例程或执行高级动态错误测试例行公事。

      【讨论】:

      • 后面几点通常使用Java代理和它们提供的Instrumentation接口来完成。特定的类加载器实现通常不用于此。不管答案多么好,我仍然 +1。
      【解决方案4】:

      answer 很好地总结了为什么您可能不想为所有类使用相同的类加载器,即使可以:

      类加载器在大型系统和服务器应用程序中用于执行以下操作:

      • 模块化系统并在运行时加载、卸载和更新模块
      • 并行使用不同版本的 API 库(例如 XML 解析器)
      • 隔离在同一 JVM 中运行的不同应用程序(确保它们不会相互干扰,例如通过静态变量)

      【讨论】:

        【解决方案5】:

        假设您正在开发应用服务器。根据要求,您将希望在服务器启动时加载类。原始加载器不知道您的要求,因此您需要编写自己的类加载器。

        why write custom class loader

        【讨论】:

          【解决方案6】:

          主要需求是隔离。

          假设一个页面上有 3 个小程序,每个小程序都使用不同版本的库 foo.jar。您希望这些小程序中的每一个都使用其自己的库版本运行,并确保它不会踩到另一个小程序的脚趾。这要归功于不同的类加载器。

          部署在单个容器上的 Web 应用程序也是如此。 Java 容器在没有部署任何应用程序的情况下启动,然后部署了一个应用程序。您希望容器能够从它甚至不知道它何时启动的位置加载类。如果部署了另一个 web 应用,您希望这个另一个应用拥有自己的类和库,它们与第一个应用的类和库不同且隔离。

          另一个需要是能够从不同的位置加载类:文件系统,但也包括 URL、数据库等。

          【讨论】:

          • 近乎完美的答案 IMO。我想扩展对隔离的需求,通过使用不同的类加载器,您还可以解决类路径冲突,例如相同类的多个副本存在于同一个 JVM 中,但不同的应用程序可能使用不同的版本(例如:一个使用 Hibernate 3.x 的应用程序和另一个使用 Hibernate 4.x 的应用程序)。
          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2011-04-02
          • 2012-07-08
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多