在robolectroc出现了
java.lang.VerifyError
java.lang.VerifyError: Expecting a stackmap frame at branch target 37
Exception Details:
Location:
略
@3: ifnonnull
Reason:
Expected stackmap frame at this location.
Bytecode:
0x0000000: b200 57c7 0022 122e 594b c2b2 0057 c700
0x0000010: 0dbb 002e 59b7 006d b300 572a c3a7 0008
0x0000020: 4c2a c32b bfb2 0057 b0
Exception Handler Table:
bci [11, 29] => handler: 32
bci [32, 35] => handler: 32
本博客的上一章从使用的层面解决了该问题
就是在JVM 加入 -noverify
根本原因如下:
JVM 加载class文件时会做字节码校验(bytecode verification).如果你的class文件是由java源文件编译出来的,那么基本上不用担心bytecode verification. 如果class文件有asm,cglib等动态生成出来的或者由其他编译的,那么JVM在校验bytecode 时就会可能失败,失败的原因是可能生成的bytecode有bug,也可能是新版本的JVM加入了新的校验条件导致原来可以通过校验的bytecode 现在不成功了.在我自己例子中:使用jdk1.7打包的SDK,使用jdk1.8做Robolectric 测试就发生了java.lang.VerifyError
而对于使用者而已,我们-noverify
就是关闭bytecode verification
####### 以下提供从SDK的层面上解决java.lang.VerifyError
关键是在混淆文件中删除
- dontpreverify
本作者将混淆文件proguard-rules.pro
的dontpreverify 注释打包之后,依然出现ava.lang.VerifyError
为什么呢?
打开build.gradle
可见:
buildTypes {
release {
minifyEnabled true
proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
}
}
自定义混淆文件proguard-rules.pro
中我已经注释了#- dontpreverify
,这个getDefaultProguardFile('proguard-android-optimize.txt')
是什么呢?
原来他是系统生成的混淆文件,我们点进去可见:
public static File getDefaultProguardFile(@NonNull String name, @NonNull Project project) {
if (!DEFAULT_PROGUARD_WHITELIST.contains(name)) {
throw new IllegalArgumentException(
"User supplied default proguard base extension "
+ "name is unsupported. Valid values are: "
+ DEFAULT_PROGUARD_WHITELIST);
}
return FileUtils.join(
project.getRootProject().getBuildDir(),// 根目录/build
AndroidProject.FD_INTERMEDIATES,// "intermediates"
"proguard-files",
name //'proguard-android-optimize.txt
+ "-" + Version.ANDROID_GRADLE_PLUGIN_VERSION);
}
根据以上的代码,我在: 项目根目录/build/intermediates/proguard-files
,找到了proguard-android-optimize.txt-2.3.3
该文件中有dontpreverify
-optimizations !code/simplification/arithmetic,!code/simplification/cast,!field/*,!class/merging/*
-optimizationpasses 5
-allowaccessmodification
-dontpreverify # 需要注释
所以,我把这个文件放在SDK 的项目目录中,将# -dontpreverify
注释掉,且在build.gradle
中引用该混淆代替系统的混淆
buildTypes {
release {
minifyEnabled true
// proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
proguardFiles 'proguard-android-optimize.txt', 'proguard-rules.pro'
}
}
打包后即可解决verifyError 的问题
以下是使用的总结:
1.在
根目录/build/intermediates/proguard-files
下,复制proguard-android-optimize.txt-2.3.3
文件到SDK下面
2.修改
build.gradle
buildTypes {
release {
minifyEnabled true
proguardFiles 'proguard-android-optimize.txt', 'proguard-rules.pro'
}
}
- 打包后就可以啦…(done)