【问题标题】:Safe class imports from JAR Files从 JAR 文件导入安全类
【发布时间】:2011-01-07 15:39:14
【问题描述】:

考虑一个 java 程序从 jar 文件中导入类的场景。如果同一个类驻留在两个或多个 jar 文件中,则可能会出现问题。

  1. 在这种情况下,程序导入的类是什么?是班级吗 使用较旧的时间戳??

  2. 我们可以遵循哪些做法来避免此类并发症。

编辑:这是一个例子。我有 2 个 jar 文件 my1.jar 和 my2.jar。这两个文件都包含 com.mycompany.CrazyWriter

【问题讨论】:

  • 同一类还有两个类——你能澄清一下吗?
  • “如果同一个班级还有两个班级”?您的意思是“如果同一个类存在于另外两个 jars 中”?
  • 根据编辑更新了问题以澄清第一句话。

标签: java class import jar class-library


【解决方案1】:

默认情况下,ClassLoader 使用按顺序搜索的类路径加载类。

如果您有同一个类的两个实现,则将加载类加载器首先找到的那个。

如果这些类实际上不是同一个类(名称相同但方法不同),则在尝试使用它时会出现异常。

您可以使用多个类加载器在单个 VM 中加载两个同名的类。 OSGI 框架可以为您管理大量复杂性,确保加载正确的版本等。

【讨论】:

    【解决方案2】:

    首先,我假设您的意思是同一个类驻留在另外两个 jar 文件中...

    现在,回答您的问题:

    1. 导入哪个类取决于您的类加载器和 JVM。你不能保证它会是哪个类,但在普通的类加载器中,它将是你类路径上第一个 jar 文件中的类。
    2. 不要将同一个类放入多个 jar 文件中,或者如果您试图覆盖系统类,请使用 -bootclasspath

    编辑:解决这个答案中的一个问题。我最初认为sealing the jar 会有所作为,因为理论上它不应该从不同的 jar 文件中从同一个包中加载两个类。然而,经过一些实验,我发现这个假设并不成立,至少对于默认的安全提供程序。

    【讨论】:

    • 1. default 类加载器(问题所在)呢? 2. 将同一类的不同版本放在多个 JAR 中(例如修补类)是有效的用例。
    • @Pascal 您可能认为这是一个有效的用例,但最好替换原来的 jar,因为通常无论如何您都需要重新启动。答案是,如上所述,类加载器将使用它首先找到的任何类。通常,这将来自类路径上的第一个 jar 文件。
    • @Paul BEA 不会给你新的 weblogic.jar 所以不,替换原来的 jar 不是更好(问题是不重启与否)。我使用过的所有 JVM 都会总是选择找到的第一个类。
    • @Pascal 我已经更新了答案,因为我认为密封罐子会产生影响,但事实并非如此。我仍然认为将同一个包拆分到多个 jar 文件中并不是一个好主意,但我承认有时它可能很有用,即使它会否定您与供应商的任何支持合同;- )
    • 关于您的编辑:当尝试从具有不同凭据的 JAR 加载同一包中的 不同 类时,JVM 将引发异常。在不同的 JAR 中拥有 same 类并不是同一个场景。
    【解决方案3】:

    ClassLoader 负责加载类。 它扫描 ClassPath 并加载它首先找到的类。 如果您在 ClassPath 上有两次相同的 Jar,或者如果您有两个包含同一类的两个不同版本的 Jar(即 com.packagename.Classname),则加载第一个找到的 Jar。

    尽量避免在类路径中使用相同的 jar 两次。

    【讨论】:

      【解决方案4】:
      1. 不确定你所说的“同一个类存在于另外两个类中”是什么意思

        如果您指的是内部/嵌套类,则应该没有问题,因为它们位于不同的命名空间中。
        如果您的意思是在另外两个 JAR 中,正如已经回答的那样,则使用类路径中的顺序。

      2. 如何避免?
        一个包应该只在一个 JAR 中以避免重复的类。如果两个类具有相同的简单名称,例如java.util.Datejava.sql.Date,但在不同的包中,它们实际上是不同的类。您必须使用完全限定名称(至少来自其中一个类)来区分它们。

      【讨论】:

        【解决方案5】:

        如果您在查找正在使用的类的哪个版本时遇到问题,那么 jwhich 可能有用: http://www.fullspan.com/proj/jwhich/index.html

        【讨论】:

        • 我希望 Eclipse 有一个带有 JAR 文件/位置列表的“找到多个类定义”警告。是否有 Eclipse 插件可以告诉您从哪里导入给定的类?我管理依赖于许多 jar 的大型项目,有时会出现冲突。这些罐子是不可变的,所以我必须重新调整构建路径才能让它们正常工作。大多数时候,很难知道是否使用了正确的文件(在构建类文件时,它们是使用对特定类的引用来构建的,它永远不会指向重复项)。
        • @ATDC 我不知道(我目前不是 Eclipse 用户),但我不认为自己编写会太难
        【解决方案6】:

        如果同一个类位于另外两个 jar 中,则应该有问题。

        你到底是什么意思?为什么应该这是个问题?

        在这种情况下,程序导入的类是什么? (时间戳较旧的类??)

        如果一个类存在于两个 JAR 中,则该类将从找到它的类路径上的第一个 JAR 加载。引用Setting the class path(引用部分也适用于存档文件):

        您指定多个类路径条目的顺序很重要。 Java 解释器将在目录中查找类按照它们在类路径变量中出现的顺序。在上面的示例中,Java 解释器将首先在目录C:\java\MyClasses 中查找所需的类。只有在该目录中找不到具有正确名称的类时,解释器才会在C:\java\OtherClasses 目录中查找。

        换句话说,如果需要特定的顺序,那么只需在类路径中显式枚举 JAR 文件。这是应用程序服务器供应商常用的东西:要修补产品的特定类,您将包含修补类的 JAR(例如 CR1234.jar)放在主 JAR 之前的类路径上(例如 weblogic.jar )。

        我们可以遵循哪些做法来避免此类并发症。

        嗯,显而易见的答案是不要这样做(或者只是像上面给出的示例那样故意这样做)。

        【讨论】:

          猜你喜欢
          • 2013-12-17
          • 1970-01-01
          • 2021-07-02
          • 1970-01-01
          • 2012-01-28
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2017-08-08
          相关资源
          最近更新 更多