我在 Maven 中有一个多模块项目,它使用(除其他外)glassfish-jersey
、jersey-moxy
、wicket-ioc
>、lucene
和 lamdbaj
这些都带有 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>
最佳答案
尝试在使用a recent version of ASM的类路径上显式添加一些cglib v3.* 。您遇到的问题是 cglib 通过继承而不是通过委托(delegate)来修改 ASM 类编写器的行为。然而,ASM 通过将其 ClassWriter
的方法设为 final
from any version 4.* 来强制执行后一种最佳实践。虽然仍然可以覆盖其方法 in version 3 。您遇到的错误是 cglib 2.* 与 ASM 4.* 组合的结果。
幸运的是(对你来说),cglib 在其上一个版本中相当静态,即只有很小的 API 更改,而较新的版本主要由 ASM 的更新组成。如果您幸运的话,这种对 cglib v3.* 的显式使用可以解决您的问题。只要您的项目依赖项都不直接依赖于 ASM,这对于您命名的 Jersey 或 Lucene 等依赖项来说似乎是合理的。
如果这不起作用,您需要在使用像 jarjar 这样的工具时重新编译一些依赖项,以便将直接 ASM 依赖项重新打包到不同的 namespace 中,从而解决这些版本冲突。另一种方法是通过一些有条件的子优先 ClassLoader
魔法来隔离不同的 ASM 版本,但这并不是那么值得推荐,因为效果是不可预测的,而且还会导致性能损失。
关于java - 管理maven不同的cglib/asm版本,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/21302318/