【问题标题】:manage maven different cglib/asm versions管理 maven 不同的 cglib/asm 版本
【发布时间】:2014-01-23 07:49:53
【问题描述】:

我在 maven 中有一个多模块项目,它使用(除其他外)glassfish-jerseyjersey-moxywicket-ioclucenelamdbaj 这些都带有 asm,但都有不同的版本。
最近,我在运行测试时遇到了很多麻烦。我得到的典型错误是:

java.lang.VerifyError: class net.sf.cglib.core.DebuggingClassWriter overrides final method visit.(IILjava/lang/String;Ljava/lang/String;Ljava/lang/String;[Ljava/lang/String;)V

我读到这可能是由不同的asm 版本引起的。有没有办法在它们的依赖项中“沙箱”这些不同的 asm 版本,这样它们就不会混淆?

编辑:

我目前的解决方案是使用jarjar,像这样:

  <build>
    <plugins>
       <plugin>
        <groupId>org.sonatype.plugins</groupId>
        <artifactId>jarjar-maven-plugin</artifactId>
        <executions>
          <execution>
            <phase>package</phase>
            <goals>
              <goal>jarjar</goal>
            </goals>
            <configuration>
              <includes>
                <include>cglib:cglib-nodep</include>
              </includes>
              <rules>
                <rule>
                  <pattern>net.sf.cglib.asm.**</pattern>
                  <result>com.myproject.lambda4j.asm.@1</result>
                </rule>
                <rule>
                  <pattern>net.sf.cglib.**</pattern>
                  <result>com.myproject.lambda4j.cglib.@1</result>
                </rule>
              </rules>
            </configuration>
          </execution>
        </executions>
      </plugin>

【问题讨论】:

  • 这正是 ASM 开发人员自己告诉您应该将 asm 重新打包到自己的命名空间而不是直接依赖它的原因 (FAQ #15),因为不能保证跨版本兼容。我很想将此报告为 Jersey、Lucene 等中的错误。
  • 人们通常在使用 cglib 时并不了解它在幕后使用 ASM。不幸的是,Cglib 没有这样的警告。

标签: java maven dependencies sandbox cglib


【解决方案1】:

尝试在使用a recent version of ASM 的类路径上显式添加一些 cglib v3.*。您遇到的问题是 cglib 通过继承而不是委托来修改 ASM 类编写器的行为。然而,ASM 通过将其ClassWriter 的方法设置为finalfrom any version 4.* 来强制执行后一种最佳实践,同时仍然可以覆盖其方法in version 3。您遇到的错误是 cglib 2.* 与 ASM 4.* 结合的结果。

幸运的是(对您而言),cglib 在其上一个版本中相当静态,即只有少量的 API 更改,而较新的版本主要包括 ASM 的更新。如果幸运的话,这种对 cglib v3.* 的显式使用可以解决您的问题。只要您的项目依赖项都没有直接依赖于 ASM,这对您命名的依赖项(如 Jersey 或 Lucene)来说似乎是合理的。

如果这不起作用,您需要在使用 jarjar 之类的工具时重新编译一些依赖项,以便将直接 ASM 依赖项重新打包到不同的名称空间中,以解决这些版本冲突。另一种方法是通过一些有条件的子优先 ClassLoader 魔术来隔离不同的 ASM 版本,但这不是那么推荐,因为效果是不可预测的,并且还会导致性能损失。

【讨论】:

  • 放弃 cglib 3.1 并从其他项目中排除 cglib 依赖项似乎可以解决问题。谢谢!
  • 唉,问题在Jenkins和我的Linux环境下都解决了;但 Windows 人似乎仍然受苦。
  • 这不应该对类路径上的结果产生影响。我猜你的 Windows 人员可能会使用另一个 IDE 来动态运行应用程序。我猜IDE会在类路径中添加一些东西。在其中一台 Windows 机器上检查任何 cglib 2.2 依赖项的类路径。我想这涉及到一些类路径缓存。使用 IntelliJ 时,重新导入所有 Maven 项目。使用 Eclipse 时,请使用 IntelliJ。
  • 目前我正在重新打包使用 JarJar 的库。到目前为止,这似乎是唯一稳定的解决方案。感谢您的支持!
最近更新 更多