Duplicate :
|
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</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.