java.lang.VerifyError:在分支目标处需要一个堆栈图帧
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/26733946/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
java.lang.VerifyError: Expecting a stackmap frame at branch target
提问by Suresh Atta
Successfully compiled the project and build as well with Maven. This is my first maven project. But I have no idea why I'm getting the below error.
成功编译项目并使用 Maven 构建。这是我的第一个 Maven 项目。但我不知道为什么会出现以下错误。
Deployeed the war on tomcat and hit my url and the below error shown in my browser.
在 tomcat 上部署War并点击我的网址,并在我的浏览器中显示以下错误。
java.lang.VerifyError: Expecting a stackmap frame at branch target 72
Exception Details:
Location:
com/ebetinc/frontend/presentation/components/Login.isToteAvailable(Ljava/lang/String;Lcom/ebetinc/frontend/dao/DatabaseDao;)Z @46: lookupswitch
Reason:
Expected stackmap frame at this location.
Bytecode:
0000000: 043d 2bb9 03a4 0100 4e2a c601 1c13 03a6
0000010: 2ab8 03aa 9900 0803 3da7 010d 2db8 03ad
0000020: 9900 692a 3a04 0236 0519 04b6 03b1 ab00
0000030: 0000 003a 0000 0002 0000 0626 0000 002c
0000040: 0000 0644 0000 001a 0019 0413 03b3 b603
0000050: b599 0017 0336 05a7 0011 1904 1303 b7b6
0000060: 03b5 9900 0604 3605 1505 ab00 0000 001c
0000070: 0000 0002 0000 0000 0000 001a 0000 0001
0000080: 0000 001a 033d a700 a02d b803 ba99 0099
0000090: 2a3a 0402 3605 1904 b603 b1ab 0000 006a
00000a0: 0000 0004 0000 af34 0000 0029 0000 af4c
00000b0: 0000 003a 0000 af4d 0000 004b 0015 51cb
00000c0: 0000 005c 1904 1303 bcb6 03b5 9900 3903
00000d0: 3605 a700 3319 0413 03be b603 b599 0028
00000e0: 0436 05a7 0022 1904 1303 c0b6 03b5 9900
00000f0: 1705 3605 a700 1119 0413 03c2 b603 b599
0000100: 0006 0636 0515 05aa 0000 001f 0000 0000
0000110: 0000 0003 0000 001d 0000 001d 0000 001d
0000120: 0000 001d 033d 1cac
Stackmap Table:
append_frame(@28,Integer,Object[#931])
append_frame(@73,Object[#200],Integer)
same_frame(@90)
same_frame(@104)
same_frame(@132)
chop_frame(@134,2)
same_frame(@137)
append_frame(@196,Object[#200],Integer)
same_frame(@213)
same_frame(@230)
same_frame(@247)
same_frame(@261)
same_frame(@292)
chop_frame(@294,2)
Can anyone throw some inputs ? Thanks for any help.
任何人都可以抛出一些输入吗?谢谢你的帮助。
Configuration:
配置:
Java 1.7
Maven 3+
回答by SubOptimal
Hi this is related to some bytecode in your application. (see this note on compatibility changes for Java 7 http://www.oracle.com/technetwork/java/javase/compatibility-417013.html#incompatibilities, look there some lines below for JSR 202)
您好,这与您的应用程序中的某些字节码有关。(请参阅有关 Java 7 兼容性更改的说明http://www.oracle.com/technetwork/java/javase/compatibility-417013.html#incompatibilities,在下面查看 JSR 202 的一些行)
You can either
你可以
- recompile all sources with JDK 7
- or in case you have no access to the source
- use
java
with paramter-XX:-UseSplitVerifier
- or switch to Java 6 if you face promblems using the switch
- use
- 使用 JDK 7 重新编译所有源代码
- 或者如果您无法访问源
java
与参数一起使用-XX:-UseSplitVerifier
- 或者如果您在使用 switch 时遇到问题,请切换到 Java 6
editEven the answer is already a bit old. Because of a current case I add some more detailed explanation.
编辑即使答案已经有点旧了。由于当前案例,我添加了一些更详细的解释。
The StackMapTable
attribute in the class file was, even not documented at that time, introduced with Java 6.
StackMapTable
类文件中的属性是在 Java 6 中引入的,当时甚至没有记录。
Foo.java
文件
public class Foo {
public static boolean bar(String s) {
if (s.length() == 0) {
return true;
}
return false;
}
}
$ java -version
java version "1.6.0"
Java(TM) SE Runtime Environment (build 1.6.0-b105)
$ javac Foo.java
$ javap -c -v Foo
Compiled from "Foo.java"
public class Foo extends java.lang.Object
SourceFile: "Foo.java"
minor version: 0
major version: 50
...
public static boolean bar(java.lang.String);
Code:
Stack=1, Locals=1, Args_size=1
0: aload_0
1: invokevirtual #2; //Method java/lang/String.length:()I
4: ifne 9
7: iconst_1
8: ireturn
9: iconst_0
10: ireturn
LineNumberTable:
line 3: 0
line 4: 7
line 6: 9
StackMapTable: number_of_entries = 1
frame_type = 9 /* same */
}
The class verifier did no check if the attribute was in the class or not.
类验证器不检查属性是否在类中。
Following creates the file Foo.class
without the StackMatTable
attribute.
以下创建Foo.class
没有该StackMatTable
属性的文件。
FooDump.java
食物转储.java
import org.objectweb.asm.*;
import java.io.*;
public class FooDump implements Opcodes {
public static void main(String[] args) throws Exception {
FileOutputStream fos = new FileOutputStream("Foo.class");
fos.write(dump());
fos.close();
}
public static byte[] dump() throws Exception {
ClassWriter cw = new ClassWriter(0);
FieldVisitor fv;
cw.visit(V1_6, ACC_PUBLIC + ACC_SUPER, "Foo", null, "java/lang/Object",
null);
MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, "<init>", "()V", null,
null);
mv.visitCode();
mv.visitVarInsn(ALOAD, 0);
mv.visitMethodInsn(INVOKESPECIAL, "java/lang/Object", "<init>", "()V",
false);
mv.visitInsn(RETURN);
mv.visitMaxs(1, 1);
mv.visitEnd();
mv = cw.visitMethod(ACC_PUBLIC + ACC_STATIC, "bar",
"(Ljava/lang/String;)Z", null, null);
mv.visitCode();
mv.visitVarInsn(ALOAD, 0);
mv.visitMethodInsn(INVOKEVIRTUAL, "java/lang/String", "length", "()I",
false);
Label l0 = new Label();
mv.visitJumpInsn(IFNE, l0);
mv.visitInsn(ICONST_1);
mv.visitInsn(IRETURN);
mv.visitLabel(l0);
// this line would generate the StackMapTable attribute
// mv.visitFrame(Opcodes.F_SAME, 0, null, 0, null);
mv.visitInsn(ICONST_0);
mv.visitInsn(IRETURN);
mv.visitMaxs(1, 1);
mv.visitEnd();
cw.visitEnd();
return cw.toByteArray();
}
}
compile and run it
编译并运行它
$ javac -cp asm-5.2.jar:asm-util-5.2.jar:. FooDump.java
$ java -cp asm-5.2.jar:asm-util-5.2.jar:. FooDump
check that the StackMapTable
attribute is not in the file
检查该StackMapTable
属性是否不在文件中
$ javap -c -v Foo
public class Foo extends java.lang.Object
minor version: 0
major version: 50
...
public static boolean bar(java.lang.String);
Code:
Stack=1, Locals=1, Args_size=1
0: aload_0
1: invokevirtual #16; //Method java/lang/String.length:()I
4: ifne 9
7: iconst_1
8: ireturn
9: iconst_0
10: ireturn
}
FooDemo.java
FooDemo.java
public class FooDemo {
public static void main(String[] args) {
System.out.println("output: " + Foo.bar(""));
}
}
$ java -version
java version "1.6.0"
Java(TM) SE Runtime Environment (build 1.6.0-b105)
$ javac FooDemo.java
$java FooDemo
output: true
With Java 7 the class verification was changed.
在 Java 7 中,类验证发生了变化。
For class files version 50 (Java 6) the check had a failover if the StackMapTable
was missing or wrong (see: jvms-4.10.1).
对于版本 50 (Java 6) 的类文件,如果StackMapTable
缺少或错误,检查会进行故障转移(请参阅:jvms-4.10.1)。
Run the check with the Foo
class version of Java 6.
使用Foo
Java 6的类版本运行检查。
$ java -version
java version "1.7.0"
Java(TM) SE Runtime Environment (build 1.7.0-b147)
$ javap -c -v Foo
Classfile /home/suboptimal/playground/Foo.class
Last modified Jun 9, 2017; size 232 bytes
MD5 checksum 5a7ea4a5dd2f6d1bcfddb9ffd720f9c9
public class Foo
minor version: 0
major version: 50 <-- class file Java 6
...
$ javac FooDemo.java
$ java FooDemo
output: true
This failover did not occur anymore for class files version 51 (Java 7).
类文件版本 51 (Java 7) 不再发生这种故障转移。
To create a Foo
class version of Java 7 amend the code of FooDump.java
.
要创建Foo
Java 7的类版本,请修改FooDump.java
.
// cw.visit(V1_6, ACC_PUBLIC + ACC_SUPER, "Foo", null, "java/lang/Object", null);
cw.visit(V1_7, ACC_PUBLIC + ACC_SUPER, "Foo", null, "java/lang/Object", null);
compile and run it
编译并运行它
$ javac -cp asm-5.2.jar:asm-util-5.2.jar:. FooDump.java
$ java -cp asm-5.2.jar:asm-util-5.2.jar:. FooDump
check that it's a class version 51
检查它是否是类版本 51
$ java -version
java version "1.7.0"
Java(TM) SE Runtime Environment (build 1.7.0-b147)
$ javap -c -v Foo
Classfile /home/suboptimal/playground/Foo.class
Last modified Jun 9, 2017; size 232 bytes
MD5 checksum cfd57fb547ac98a1b2808549f5e9e8c1
public class Foo
minor version: 0
major version: 51 <-- class file Java 7
...
$ javac FooDemo.java
$ java FooDemo
Exception in thread "main" java.lang.VerifyError: Expecting a stackmap frame at branch target 9 in method Foo.bar(Ljava/lang/String;)Z at offset 4
In Java 7 the type check for the StackMapTable
attribute can be disabled to step back to the Java 6 failover mechanism using option UseSplitVerifier.
在 Java 7 中,StackMapTable
可以使用选项UseSplitVerifier禁用对属性的类型检查以退回到 Java 6 故障转移机制。
$ java -version
java version "1.7.0"
Java(TM) SE Runtime Environment (build 1.7.0-b147)
$ java -XX:-UseSplitVerifier FooDemo
output: true
In Java 8 the verification of the StackMapTable
attribute became mandatory and the option UseSplitVerifier
was removed.
在 Java 8 中,StackMapTable
属性的验证成为强制性的,UseSplitVerifier
并删除了该选项。
$ java -version
java version "1.8.0"
Java(TM) SE Runtime Environment (build 1.8.0-b132)
$ javap -c -v Foo
Classfile /home/suboptimal/playground/Foo.class
Last modified Jun 9, 2017; size 232 bytes
MD5 checksum cfd57fb547ac98a1b2808549f5e9e8c1
public class Foo
minor version: 0
major version: 51 <-- class file Java 7
...
$ javac FooDemo.java
$ java FooDemo
Exception in thread "main" java.lang.VerifyError: Expecting a stackmap frame at branch target 9
$ java -XX:-UseSplitVerifier FooDemo
Java HotSpot(TM) 64-Bit Server VM warning: ignoring option UseSplitVerifier; support was removed in 8.0
Exception in thread "main" java.lang.VerifyError: Expecting a stackmap frame at branch target 9
noteTo use always the initial version of Java 6/7/8 was done by intention to show that the behaviour was there from the beginning.
注意始终使用 Java 6/7/8 的初始版本是为了表明行为从一开始就存在。
You might find some suggestions to get it running with Java 8 ...
您可能会发现一些建议使其与 Java 8 一起运行......
$ java -noverify FooDemo
output: true
$ java -Xverify:none FooDemo
output: true
noteThis disables the bytecode verifier. Keep in mind to never disable bytecode verification in a production system.
注意这会禁用字节码验证器。请记住永远不要在生产系统中禁用字节码验证。
回答by LucasNz
I've had the same problem running a Java 1.7 Web Application on a Java 1.7 Weblogic 12C server, while trying to deploy the error occurs:
我在 Java 1.7 Weblogic 12C 服务器上运行 Java 1.7 Web 应用程序时遇到了同样的问题,但在尝试部署时发生了错误:
java.lang.VerifyError: Expecting a stackmap frame at branch target 15
Exception Details: Location: aClassPathWithClassName.$javassist_write_aSpecificField(Ljava/lang/Long;)V
@6: ifnonnull Reason: Expected stackmap frame at this location.
Bytecode: 0000000: 2ab9 00cc 0100 c700 092a 2bb5 00ce b12a 0000010: 59b9 00d0 0100 2a12 d12a b400 ce2b
b900 0000020: d505 00c0 0081 b500 ceb1
From all classes within the project it happened only with the class being instrumented, aClassPathWithClassName (in the error output above).
在项目中的所有类中,它只发生在被检测的类aClassPathWithClassName(在上面的错误输出中)。
My local solution:
我的本地解决方案:
Locate javassist lib being used by the application on the POM and update it. Here it was 3.10.0.GA, changed to 3.24.1-GA.
在 POM 上找到应用程序正在使用的 javassist 库并更新它。这里是 3.10.0.GA ,更改为3.24.1-GA。