Uploaded image for project: 'JDK'
  1. JDK
  2. JDK-7092736

java.lang.VerifyError: method: next signature: ()L Incompatible object argument

XMLWordPrintable

    • Icon: Bug Bug
    • Resolution: Duplicate
    • Icon: P4 P4
    • None
    • 6u26
    • tools
    • x86
    • linux

      FULL PRODUCT VERSION :
      java version "1.6.0_26"
      Java(TM) SE Runtime Environment (build 1.6.0_26-b03)
      Java HotSpot(TM) Server VM (build 20.1-b02, mixed mode)


      ADDITIONAL OS VERSION INFORMATION :
      Reproduced on:
      1) Linux 2.6.35-30-generic #56-Ubuntu SMP Mon Jul 11 20:00:22 UTC 2011 i686 GNU/Linux
      2) (Mac OS X) Darwin Kernel Version 11.0.0

      A DESCRIPTION OF THE PROBLEM :
      In this method:

          public Iterable<Unit> all() {
              final Unit[] units = new Unit[] {new Unit()};
              final Ref<Integer> count = new Ref<Integer>(0);

              return new Iterable<Unit>() {
                  @Override
                  public Iterator<Unit> iterator() {
                      return new Iterator<Unit>() {
                          @Override
                          public boolean hasNext() {
                              return false;
                          }

                          @Override
                          public Unit next() {
                              System.out.println("HERE I AM");
                              // this next line is the offending line - even though this code is NEVER executed!
                              // it has to do with the reference to units[count.t++]...
                              System.out.println(units[count.t++]);
                              return null;
                          }

                          @Override
                          public void remove() {
                          }
                      };
                  }
              };
          }

      ... the call to next() never gets calls but the java runtime will fail with a VerifyError because of the line: units[count.t++].

      Any changes to the construct will make the runtime work.

      STEPS TO FOLLOW TO REPRODUCE THE PROBLEM :
      1. Here is the source:


      package sandbox;

      import java.util.Iterator;

      import org.junit.Test;

      public class UnitTest {

        /**
         * works all the time
         */
        @Test
        public void sanity() {
          final Ref<Integer> count = new Ref<Integer>(0);
          for (Unit user : new Iterable<Unit>() {
            @Override
            public Iterator<Unit> iterator() {
              return new Iterator<Unit>() {
                @Override
                public boolean hasNext() {
                  return false;
                }

                @Override
                public Unit next() {
                  System.out.println(count.t++);
                  return null;
                }

                @Override
                public void remove() {
                }
              };
            };
          }) {
            System.out.println(user);
          }
        }

        /**
         * Doesn't work when executed through maven (on mac ox X as well as Ubuntu
         * 10.10; jdk 1.6.0_26.)
         *
         * ... but works when run through Eclipse
         *
         * strangeJdk16Issue(sandbox.FileStorageTest): (class:
         * sandbox/FileStorageTest$2$1, method: next signature: ()Lsandbox/Unit;)
         * Incompatible object argument for function call
         *
         * seems to be related to the remove() call to deleteRecursive()
         */
        @Test
        public void strangeJdk16Issue() throws Exception {
          for (Unit unit : all()) {
            System.out.println(unit);
          }
        }

        public Iterable<Unit> all() {
          final Unit[] units = new Unit[] { new Unit() };
          final Ref<Integer> count = new Ref<Integer>(0);

          return new Iterable<Unit>() {
            @Override
            public Iterator<Unit> iterator() {
              return new Iterator<Unit>() {
                @Override
                public boolean hasNext() {
                  return false;
                }

                @Override
                public Unit next() {
                  System.out.println("HERE I AM");
                  // this next line is the offending line - even though this code is
                  // NEVER executed!
                  // it has to do with the reference to units[count.t++]...
                  System.out.println(units[count.t++]);
                  return null;
                }

                @Override
                public void remove() {
                }
              };
            }
          };
        }

        
        private static class Unit {

        }

        
        public class Ref<T> {
          public T t;

          public Ref(T t) {
            this.t = t;
          }

          public Ref() {
          }
        }
        
      }


      2. I would suggest creating a maven project to simplify the execution; here is my pom.xml:
      <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
        xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
        <modelVersion>4.0.0</modelVersion>

        <groupId>sandbox</groupId>
        <artifactId>jdk16-issue</artifactId>
        <version>1.0</version>
        <packaging>jar</packaging>

        <name>jdk16-issue</name>
        <url>http://maven.apache.org&lt;/url>

        <properties>
          <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
        </properties>

        <build>
          <plugins>
            <!--plugin>
              <groupId>org.apache.maven.plugins</groupId>
              <artifactId>maven-enforcer-plugin</artifactId>
              <executions>
                <execution>
                  <id>enforce-versions</id>
                  <goals>
                    <goal>enforce</goal>
                  </goals>
                  <configuration>
                    <rules>
                      <requireJavaVersion>
                        <version>1.6</version>
                      </requireJavaVersion>
                    </rules>
                  </configuration>
                </execution>
              </executions>
            </plugin-->
            
            <plugin>
                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-compiler-plugin</artifactId>
                <version>2.3.2</version>
                <configuration>
                  <compilerVersion>1.6</compilerVersion>
                  <source>1.6</source>
                  <target>1.6</target>
                  <testSource>1.6</testSource>
                  <testTarget>1.6</testTarget>
                  <compilerArguments>
                    <verbose/>
                  </compilerArguments>
               </configuration>
            </plugin>
          
            <!--plugin>
              <artifactId>maven-surefire-plugin</artifactId>
              <version>2.9</version>
              <configuration>
                <systemProperties>
                </systemProperties>
              </configuration>
            </plugin-->

          </plugins>
        </build>

        <dependencies>
          <dependency>
            <groupId>junit</groupId>
            <artifactId>junit</artifactId>
            <version>4.8.2</version>
            <scope>test</scope>
          </dependency>
        </dependencies>
      </project>


      3. mvn clean install


      EXPECTED VERSUS ACTUAL BEHAVIOR :
      EXPECTED -

      -------------------------------------------------------------------------------
      Test set: sandbox.UnitTest
      -------------------------------------------------------------------------------
      Tests run: 2, Failures: 0, Errors: 1, Skipped: 0, Time elapsed: 0.022 sec <<< FAILURE!
      strangeJdk16Issue(sandbox.UnitTest) Time elapsed: 0.003 sec <<< ERROR!
      java.lang.VerifyError: (class: sandbox/UnitTest$2$1, method: next signature: ()Lsandbox/UnitTest$Unit;) Incompatible object argument for function call
              at sandbox.UnitTest$2.iterator(UnitTest.java:66)
              at sandbox.UnitTest.strangeJdk16Issue(UnitTest.java:54)
              at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
              at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
              at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
              at java.lang.reflect.Method.invoke(Method.java:597)
              at org.junit.runners.model.FrameworkMethod$1.runReflectiveCall(FrameworkMethod.java:44)
              at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:15)
              at org.junit.runners.model.FrameworkMethod.invokeExplosively(FrameworkMethod.java:41)
              at org.junit.internal.runners.statements.InvokeMethod.evaluate(InvokeMethod.java:20)
              at org.junit.runners.BlockJUnit4ClassRunner.runNotIgnored(BlockJUnit4ClassRunner.java:79)
              at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:71)
              at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:49)
              at org.junit.runners.ParentRunner$3.run(ParentRunner.java:193)
              at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:52)
              at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:191)
              at org.junit.runners.ParentRunner.access$000(ParentRunner.java:42)
              at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:184)
              at org.junit.runners.ParentRunner.run(ParentRunner.java:236)
              at org.apache.maven.surefire.junit4.JUnit4TestSet.execute(JUnit4TestSet.java:62)
              at org.apache.maven.surefire.suite.AbstractDirectoryTestSuite.executeTestSet(AbstractDirectoryTestSuite.java:140)
              at org.apache.maven.surefire.suite.AbstractDirectoryTestSuite.execute(AbstractDirectoryTestSuite.java:127)
              at org.apache.maven.surefire.Surefire.run(Surefire.java:177)
              at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
              at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:39)
              at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
              at java.lang.reflect.Method.invoke(Method.java:597)
              at org.apache.maven.surefire.booter.SurefireBooter.runSuitesInProcess(SurefireBooter.java:345)
              at org.apache.maven.surefire.booter.SurefireBooter.main(SurefireBooter.java:1009)


      REPRODUCIBILITY :
      This bug can be reproduced always.

      CUSTOMER SUBMITTED WORKAROUND :
        Interestingly the problem does not show up when the testcase is run from Eclipse.

      I compared the compiled classes between eclipse and maven and there are differences but I wasn't able to discern the way eclipse compiled the code.

      Regardless, there seems to be a bug in either javac or java.

            Unassigned Unassigned
            webbuggrp Webbug Group
            Votes:
            0 Vote for this issue
            Watchers:
            0 Start watching this issue

              Created:
              Updated:
              Resolved:
              Imported:
              Indexed: