java.lang.VerifyError:在分支目标处期望堆栈图帧 [英] java.lang.VerifyError: Expecting a stackmap frame at branch target

查看:30
本文介绍了java.lang.VerifyError:在分支目标处期望堆栈图帧的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

成功编译项目并使用 Maven 构建.这是我的第一个 Maven 项目.但我不知道为什么会出现以下错误.

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.

在 tomcat 上部署 war 并点击我的网址,并在我的浏览器中显示以下错误.

Deployeed the war on tomcat and hit my url and the below error shown in my browser.

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.

配置:

Java 1.7
Maven 3+

推荐答案

这与您的应用程序中的某些字节码有关.(请参阅有关 Java 7 兼容性更改的说明 http://www.oracle.com/technetwork/java/javase/compatibility-417013.html#incompatibility,看看下面的一些 JSR 202 行)

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)

你可以

  • 使用 JDK 7 重新编译所有源代码
  • 或者如果您无法访问源
    • 使用 java 和参数 -XX:-UseSplitVerifier
    • 如果您在使用 switch 时遇到问题,请切换到 Java 6

    edit 即使答案已经有点旧了.由于当前案例,我添加了一些更详细的解释.

    edit Even the answer is already a bit old. Because of a current case I add some more detailed explanation.

    Java 6 引入了类文件中的 StackMapTable 属性,当时甚至没有记录.

    The StackMapTable attribute in the class file was, even not documented at that time, introduced with 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.

    以下创建没有 StackMatTable 属性的文件 Foo.class.

    Following creates the file Foo.class without the StackMatTable attribute.

    FooDump.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();
        }
    }
    

    编译运行

    $ 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
    

    检查 StackMapTable 属性是否不在文件中

    check that the StackMapTable attribute is not in the file

    $ 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

    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
    

    Java 7 更改了类验证.

    With Java 7 the class verification was changed.

    对于版本 50 (Java 6) 的类文件,如果 StackMapTable 丢失或错误,检查会进行故障转移(请参阅:jvms-4.10.1).

    For class files version 50 (Java 6) the check had a failover if the StackMapTable was missing or wrong (see: jvms-4.10.1).

    使用 Java 6 的 Foo 类版本运行检查.

    Run the check with the Foo class version of 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
    

    类文件版本 51 (Java 7) 不再发生这种故障转移.

    This failover did not occur anymore for class files version 51 (Java 7).

    要创建Java 7的Foo类版本,请修改FooDump.java的代码.

    To create a Foo class version of Java 7 amend the code of 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);
    

    编译运行

    $ 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
    

    检查它是否是类版本 51

    check that it's a class version 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
    

    在 Java 7 中,可以禁用对 StackMapTable 属性的类型检查,以使用选项 UseSplitVerifier.

    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 -version
    java version "1.7.0"
    Java(TM) SE Runtime Environment (build 1.7.0-b147)
    
    $ java -XX:-UseSplitVerifier FooDemo
    output: true
    

    在 Java 8 中,StackMapTable 属性的验证成为强制性的,并且删除了选项 UseSplitVerifier.

    In Java 8 the verification of the StackMapTable attribute became mandatory and the option UseSplitVerifier was removed.

    $ 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
    

    注意始终使用 Java 6/7/8 的初始版本是为了表明行为从一开始就存在.

    note To 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 8 一起运行......

    You might find some suggestions to get it running with Java 8 ...

    $ java -noverify FooDemo
    output: true
    
    $ java -Xverify:none FooDemo
    output: true
    

    注意 这会禁用字节码验证器.请记住永远不要在生产中禁用字节码验证系统.

    note This disables the bytecode verifier. Keep in mind to never disable bytecode verification in a production system.

    这篇关于java.lang.VerifyError:在分支目标处期望堆栈图帧的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆