Uploaded image for project: 'Javassist'
  1. Javassist
  2. JASSIST-160

Java.lang.VerifyErrors occur in specific cases when using javaassist with Java 1.7

    Details

    • Type: Bug
    • Status: Closed (View Workflow)
    • Priority: Major
    • Resolution: Done
    • Affects Version/s: 3.16.1-GA
    • Fix Version/s: 3.17.0-GA
    • Labels:
      None
    • Environment:

      jdk1.7.0_03 on Windows XP SP 3

    • Steps to Reproduce:
      Hide

      I'm attaching to this bug a self contained example where you can see both type of errors.
      The example includes all source files needed and scripts to build and run.
      You will need both Java 1.6 and Java 1.7 installed on your machine to run the full test and see the difference.

      To run the test:

      1. Extract the attached jatest.zip file to your machine.
      2. Edit the files test1.6.bat and test1.7.bat and adjust the paths to your Java 1.6 and 1.7 installations respectively.
      If you are running on a non-windows platform you can easily translate these scripts to the target platform.
      3. Run both test1.6.bat and test1.7.bat. These two scripts build and run the same test with Java 1.6 and Java 1.7 respectively.
      4. Each x script (x= 1.6, 1.7) does the following:
      Compiles the source files.
      Creates a testx.jar file.
      Runs the class TraceJar against the testx.jar.
      TraceJar uses javaassist to insert simple print statements into each method using insertBefore and insertAfter. It creates a new testxT.jar
      Runs the Main test class against the generated testxT.jar.
      The test tries to load the two test classes Test1 and Test2 and then also tries to run through some of their methods.

      You can see that all this works fine with Java 1.6 but fails with Java 1.7.
      See below the output with Java 1.6 vs. the output with Java 1.7.

      Note that getting the second type of error - Bad return type - is quite easy. All it takes is a simple method like the one in Test2.
      The first type of error - Inconsistent stackmap frames - seems to occur only for a very specific code pattern as in Test1. Changing that code even slightly results in either a valid class or in the Bad return type error.

      Output with Java 1.6:

      ...
      Running test with jar16T.jar
      before method Main.main(java.lang.String[]), params=[[Ljava.lang.String;@1f33675]
      before method Main.loadClass(java.lang.String), params=[Test1]
      loading test class Test1
      class was loaded succesfuly
      after method Main.loadClass(java.lang.String), retval=null
      before method Main.loadClass(java.lang.String), params=[Test2]
      loading test class Test2
      class was loaded succesfuly
      after method Main.loadClass(java.lang.String), retval=null
      before method Main.runTest1()
      before method Test1.f(Info), params=[Info@19ee1ac]
      before method Test1.createHolder()
      after method Test1.createHolder()
      before method Info.createChild(Holder), params=[Holder@1befab0]
      after method Info.createChild(Holder)
      before method Child.init()
      after method Child.init(), retval=null
      after method Test1.f(Info)
      before method Test1.f(Info), params=[SubInfo@13c5982]
      before method Test1.createHolder()
      after method Test1.createHolder()
      before method SubInfo.createChild(Holder), params=[Holder@1186fab]
      after method SubInfo.createChild(Holder)
      before method Child.init()
      after method Child.init(), retval=null
      after method Test1.f(Info)
      after method Main.runTest1(), retval=null
      before method Main.runTest2()
      before method Test2.f()
      after method Test2.f()
      after method Main.runTest2(), retval=null
      after method Main.main(java.lang.String[]), retval=null

      Output with Java 1.7:

      ...
      Running test with jar17T.jar
      before method Main.main(java.lang.String[]), params=[[Ljava.lang.String;@1489c06]
      before method Main.loadClass(java.lang.String), params=[Test1]
      loading test class Test1
      failed to load class
      java.lang.VerifyError: Inconsistent stackmap frames at branch target 68 in method Test1.f(LInfo;)LParent; at offset 61
      at java.lang.Class.forName0(Native Method)
      at java.lang.Class.forName(Class.java:186)
      at Main.loadClass(Main.java:16)
      at Main.main(Main.java:7)
      after method Main.loadClass(java.lang.String), retval=null
      before method Main.loadClass(java.lang.String), params=[Test2]
      loading test class Test2
      failed to load class
      java.lang.VerifyError: Bad return type in method Test2.f()LParent; at offset 22
      at java.lang.Class.forName0(Native Method)
      at java.lang.Class.forName(Class.java:186)
      at Main.loadClass(Main.java:16)
      at Main.main(Main.java:8)
      after method Main.loadClass(java.lang.String), retval=null
      before method Main.runTest1()
      failed to run test1
      java.lang.VerifyError: Inconsistent stackmap frames at branch target 68 in method Test1.f(LInfo;)LParent; at offset 61
      at Main.runTest1(Main.java:27)
      at Main.main(Main.java:9)
      after method Main.runTest1(), retval=null
      before method Main.runTest2()
      failed to run test2
      java.lang.VerifyError: Bad return type in method Test2.f()LParent; at offset 22
      at Main.runTest2(Main.java:38)
      at Main.main(Main.java:10)
      after method Main.runTest2(), retval=null
      after method Main.main(java.lang.String[]), retval=null

      Show
      I'm attaching to this bug a self contained example where you can see both type of errors. The example includes all source files needed and scripts to build and run. You will need both Java 1.6 and Java 1.7 installed on your machine to run the full test and see the difference. To run the test: 1. Extract the attached jatest.zip file to your machine. 2. Edit the files test1.6.bat and test1.7.bat and adjust the paths to your Java 1.6 and 1.7 installations respectively. If you are running on a non-windows platform you can easily translate these scripts to the target platform. 3. Run both test1.6.bat and test1.7.bat. These two scripts build and run the same test with Java 1.6 and Java 1.7 respectively. 4. Each x script (x= 1.6, 1.7) does the following: Compiles the source files. Creates a testx.jar file. Runs the class TraceJar against the testx.jar. TraceJar uses javaassist to insert simple print statements into each method using insertBefore and insertAfter. It creates a new testxT.jar Runs the Main test class against the generated testxT.jar. The test tries to load the two test classes Test1 and Test2 and then also tries to run through some of their methods. You can see that all this works fine with Java 1.6 but fails with Java 1.7. See below the output with Java 1.6 vs. the output with Java 1.7. Note that getting the second type of error - Bad return type - is quite easy. All it takes is a simple method like the one in Test2. The first type of error - Inconsistent stackmap frames - seems to occur only for a very specific code pattern as in Test1. Changing that code even slightly results in either a valid class or in the Bad return type error. Output with Java 1.6: ... Running test with jar16T.jar before method Main.main(java.lang.String[]), params=[ [Ljava.lang.String;@1f33675] before method Main.loadClass(java.lang.String), params= [Test1] loading test class Test1 class was loaded succesfuly after method Main.loadClass(java.lang.String), retval=null before method Main.loadClass(java.lang.String), params= [Test2] loading test class Test2 class was loaded succesfuly after method Main.loadClass(java.lang.String), retval=null before method Main.runTest1() before method Test1.f(Info), params= [Info@19ee1ac] before method Test1.createHolder() after method Test1.createHolder() before method Info.createChild(Holder), params= [Holder@1befab0] after method Info.createChild(Holder) before method Child.init() after method Child.init(), retval=null after method Test1.f(Info) before method Test1.f(Info), params= [SubInfo@13c5982] before method Test1.createHolder() after method Test1.createHolder() before method SubInfo.createChild(Holder), params= [Holder@1186fab] after method SubInfo.createChild(Holder) before method Child.init() after method Child.init(), retval=null after method Test1.f(Info) after method Main.runTest1(), retval=null before method Main.runTest2() before method Test2.f() after method Test2.f() after method Main.runTest2(), retval=null after method Main.main(java.lang.String[]), retval=null Output with Java 1.7: ... Running test with jar17T.jar before method Main.main(java.lang.String[]), params=[ [Ljava.lang.String;@1489c06] before method Main.loadClass(java.lang.String), params= [Test1] loading test class Test1 failed to load class java.lang.VerifyError: Inconsistent stackmap frames at branch target 68 in method Test1.f(LInfo;)LParent; at offset 61 at java.lang.Class.forName0(Native Method) at java.lang.Class.forName(Class.java:186) at Main.loadClass(Main.java:16) at Main.main(Main.java:7) after method Main.loadClass(java.lang.String), retval=null before method Main.loadClass(java.lang.String), params= [Test2] loading test class Test2 failed to load class java.lang.VerifyError: Bad return type in method Test2.f()LParent; at offset 22 at java.lang.Class.forName0(Native Method) at java.lang.Class.forName(Class.java:186) at Main.loadClass(Main.java:16) at Main.main(Main.java:8) after method Main.loadClass(java.lang.String), retval=null before method Main.runTest1() failed to run test1 java.lang.VerifyError: Inconsistent stackmap frames at branch target 68 in method Test1.f(LInfo;)LParent; at offset 61 at Main.runTest1(Main.java:27) at Main.main(Main.java:9) after method Main.runTest1(), retval=null before method Main.runTest2() failed to run test2 java.lang.VerifyError: Bad return type in method Test2.f()LParent; at offset 22 at Main.runTest2(Main.java:38) at Main.main(Main.java:10) after method Main.runTest2(), retval=null after method Main.main(java.lang.String[]), retval=null

      Description

      We found at least two different cases where inserting bytecode using javaassist results in a class that cannot be loaded with Java 1.7.

      java.lang.VerifyError: Inconsistent stackmap frames at branch target
      java.lang.VerifyError: Bad return type in method

      The exact same code injection on the exact same classes works fine with Java 1.6.
      We upgraded to the latest version of javaassist - 3.16.1.GA, but it didn't solve the problem.

      I'm attaching to this bug a self contained example where you can see both type of errors.
      More details in "Steps to Reproduce".

        Gliffy Diagrams

          Attachments

            Issue Links

              Activity

                People

                • Assignee:
                  chiba Shigeru Chiba
                  Reporter:
                  avners Avner Singerman
                • Votes:
                  11 Vote for this issue
                  Watchers:
                  22 Start watching this issue

                  Dates

                  • Created:
                    Updated:
                    Resolved: