java.lang.VerifyError:堆栈映射与异常处理程序中的不匹配

时间:2019-02-21 10:06:15

标签: java jvm bytecode jvm-bytecode

在JVM加载字节码期间,此java.lang.VerifyError带有如下代码段。

try{
-----
}  catch (NumberFormatException|CalculationException e) {

}

此处CalculationException是自定义异常,它扩展了java.lang.RuntimeException,而NumberFormatException是标准Java RuntimeException。 在代码编译并在本地Windows机器上运行良好的情况下。

它在QA / prod / Dev Unix节点之一上失败,并带有VerifyError,并且在其他UNIX节点上正常工作。虽然两个Unix节点都具有相同的配置(使用RedHat 6.2和1.8 jdk以及相同版本的jar文件),但也比较了javap -c在两个节点上生成的字节码,并发现相同。

我也在错误的节点上找到了两种解决此问题的方法。

1)由于此错误即将在字节码验证步骤中出现,请通过在dev unix框上将字节码验证禁用为-Xverify:none进行尝试(也尝试了-XX:-UseSplitVerifier但dint正常工作,因为我认为已从杰克8) 但是,由于我们不会在生产中禁用字节码验证,因此一直在寻找其他解决方法。

2)另一个解决方法是使用父异常:catch块中的RuntimeException而不是合并两个异常。

如果Java确实存在这种捕获方式的问题,为什么我不能理解,为什么编译器dint抱怨它,为什么它在一台机器上可以工作而不能在其他具有相同配置的机器上工作。 同样,错误原因也没有意义,它说:不能将CalculationException(当前帧,stack [0])分配给'java / lang / RuntimeException 而实际上是由

测试分配的
if (RuntimeException.class.isAssignableFrom(CalculationException.class)){
    System.out.println("Assisgnable");
}

完整异常详细信息:   位置:

    com/markit/valuations/marketdata/snapper/domain/credit/BeanWrapperBuilder_CDXOCompositeVolSurface.getSpreadVol(Lcom/markit/valuations/dates/ImmutableDate;Lcom/markit/valuations/marketdata/data/indexeddata/IndexedData;DLcom/markit/valuations/dates/ImmutableDate;Lcom/markit/valuations/dates/ImmutableDate;Ljava/lang/String;Ljava/lang/String;Lcom/markit/qag/analytics/credit/indexpv/swaption/CreditIndexSwaptionCalculator;Ljava/lang/String;Ljava/lang/String;)Ljava/lang/Double; @51: astore
  Reason:
    Type 'com/markit/valuations/common/CalculationException' (current frame, stack[0]) is not assignable to 'java/lang/RuntimeException' (stack map, stack[0])
  Current Frame:
    bci: @0
    flags: { }
    locals: { 'com/markit/valuations/marketdata/snapper/domain/credit/BeanWrapperBuilder_CDXOCompositeVolSurface', 'com/markit/valuations/dates/ImmutableDate', 'com/markit/valuations/marketdata/data/indexeddata/IndexedData', double, double_2nd, 'com/markit/valuations/dates/ImmutableDate', 'com/markit/valuations/dates/ImmutableDate', 'java/lang/String', 'java/lang/String', 'com/markit/qag/analytics/credit/indexpv/swaption/CreditIndexSwaptionCalculator', 'java/lang/String', 'java/lang/String' }
    stack: { 'com/markit/valuations/common/CalculationException' }
  Stackmap Frame:
    bci: @51
    flags: { }
    locals: { 'com/markit/valuations/marketdata/snapper/domain/credit/BeanWrapperBuilder_CDXOCompositeVolSurface', 'com/markit/valuations/dates/ImmutableDate', 'com/markit/valuations/marketdata/data/indexeddata/IndexedData', double, double_2nd, 'com/markit/valuations/dates/ImmutableDate', 'com/markit/valuations/dates/ImmutableDate', 'java/lang/String', 'java/lang/String', 'com/markit/qag/analytics/credit/indexpv/swaption/CreditIndexSwaptionCalculator', 'java/lang/String', 'java/lang/String' }
    stack: { 'java/lang/RuntimeException' }
  Bytecode:
    0x0000000: 2c19 0ab9 0015 0200 b800 cb2b 1906 ba00
    0x0000010: cc00 00b6 00cd ba00 ce00 00b6 00cf 1909
    0x0000020: ba00 d000 00b6 00cf 0eb8 003b b600 d1c0
    0x0000030: 0091 b03a 0cbb 0048 59b7 0049 12d3 b600
    0x0000040: 4b19 0ab6 004b 12d4 b600 4b2c 1254 b900
    0x0000050: 1502 00b6 004b 12d5 b600 4b29 b600 4c12
    0x0000060: d6b6 004b 1907 b600 4b12 d7b6 004b 1905
    0x0000070: b600 5b12 d8b6 004b 1906 b600 5b12 d9b6
    0x0000080: 004b 190b b600 4b12 dab6 004b 1908 b600
    0x0000090: 4bb6 004d 3a0d b200 4719 0d19 0cb9 0081
    0x00000a0: 0300 0eb8 003b b0
  Exception Handler Table:
    bci [0, 50] => handler: 51
    bci [0, 50] => handler: 51
  Stackmap Table:
  same_locals_1_stack_item_frame(@51,Object[#535])

3 个答案:

答案 0 :(得分:0)

原因

当我的依赖项中存在相同库 (Jar) 的冲突版本时,这发生在我身上。更具体地说,我导入了不同版本的 Jackson 库 v2.9.10 和 v2.11.0。

问题排查

以详细模式启动您的应用程序并使 java 记录它正在加载的所有类,以查看冲突类的来源。这可以通过传递标志 -verbose:class

修复

  • 删除冲突版本的依赖项,并确保所有相关的依赖项/库都具有相同的主要版本(至少),并且最好也具有相同的次要版本。
  • 删除可传递导入冲突版本的直接依赖项的依赖项。
  • 如果您在使用 mvn dependency:tree 或 Maven Helper 插件后没有看到任何冲突的依赖项,则冲突的依赖项可能是由库的类路径之一导入的。我知道这听起来很奇怪,因为只有应用程序应该有类路径,但是如果有人在他们的库 pom 文件中添加了 <addClasspath>true</addClasspath>,它可能会导致这种情况。

答案 1 :(得分:0)

依赖崩溃是 Aditya 指出的原因。如果您使用的是 SBT,请按照以下方法解决。

首先,将依赖关系图添加到您的全局插件 ~/.sbt/1.0/plugins/plugins.sbt

  • SBT 1.4+:添加
    addDependencyTreePlugin
    
  • SBT <1.3:添加
    addSbtPlugin("net.virtual-void" % "sbt-dependency-graph" % "0.10.0-RC1")
    

然后在你的项目中运行

sbt "whatDependsOn com.fasterxml.jackson.core jackson-databind"

were com.fasterxml.jackson.core 是组织,jackson-databind 是冲突库的工件名称。我的也是因为 play-json 使用 2.10.4 而 Confluent 包使用 2.9.9。您必须根据收到的错误消息找到您的错误消息。

那么从现在开始,您需要决定如何解决它。升级包,或降级,或排除库。在我的场景中,因为 play-json 是来自一个在我的应用程序中并不重要的库的传递依赖项,所以我选择了最简单的路径并从 2.10.4 库中排除了 play-json

答案 2 :(得分:-4)

您需要在配置中设置以下jvm参数:

-XX:-UseSplitVerifier