java.lang.VerifyError: Expecting a stackmap frame xxxx

最近在测试一个java写的项目的时候遇到这个坑爹的问题。作为一个c++开发,看到这个报错表示慌的不行。这个错误后面就是一个Location,报出了具体调用的函数名,然后下面是描述:

 Expected a stackmap frame at this locaiton

然后就是一堆看不懂的Bytecode,之后是一个Stackmap Table,同样看不懂。

我相信给出的信息看不懂是我菜的缘故。嗯。

问了有经验的同事,告知:

这个可能是因为1.8的jdk加载了1.6的jdk编译的jar包的缘故

jdk在1.7版本引入一个校验机制,要求jar包的每个罗列出来的字段都进行校验,这里要求jar包提供两个信息:1,需要校验的字段,2,校验结果。这些内容在1.6是可选的,在1.7之后变成了默认必选。看起来合情合理。

于是我替换了jar包,真的就修复了。正当我以为问题fix,重新丢给测试测的时候,测试走cd,一个部署,又gg了。

嗯???难道问题不是出在jar包,而是部署过程?

仔细跟测试确认流程,发现测试部署的jar包跟我的jar包不同。照说我们开发环境和测试环境用的是一个source,版本号也是固定的,怎么会有这种问题呢?

再仔细确认,发现测试同学有两个版本:带jcov的,不带jcov的。。。。

不带jcov的版本,部署出来的jar包跟我拉取的是相同的,并且部署结果ok。带jcov的版本才有问题。

那好,现在的问题变成了带jcov的版本到底为啥不一样呢?拉了部署流程的同事一确认,jcov有三种方式hack来得到代码覆盖率:

  1. hack jvm
  2. hack class文件
  3. hack 源文件

本着不修改源文件,改jvm太麻烦的原则,他们hack了class文件。。。。然后没有修复校验值。。。。

最后的最后,为了能跑起带jcov的版本,我们只能跳过校验值,不校验了。

具体方法就是,使用java执行代码的时候加入-noverify参数,强制跳过校验。然后,就ok了。

生产环境不建议使用这个方法,因为可能存在的磁盘损毁等原因,这个校验是非常有必要的安全手段,可以帮助尽早暴露问题。

你可能感兴趣的:(编程语言)