Feedback regarding Java 'yield'

· Not CodeYielder

It's definitely been an exciting couple of weeks. Ever since I published the code for the yield-like feature (project site here) there has been a few mentions of it over other blogs (Tech Sweep, Neal Gafter's blog, Lambda the Ultimate and even a reminder of when not to use such a framework from WarpedJavaGuy). In a very short time, downloads reached 75. And it makes me wonder: How many of these used it, tried it, had trouble with it? I didn't get any feedback; and I'd really like some! As for myself, I wrote the yielder for tree iterations, and I use it for that at the moment. It works great, creates the implicit stack and returns the elements at the order chosen - and I'm really happy with it. But what about you?

Comments (11)

Avah
Wow, thanks! Can you describe the bug in the issues section of the project?
Chaotic Java » Yielder: Eclipse bug revealed, newsgroup created
[...] For some people the Yielder test cases didn’t pass properly. Readers Hanson Char and Michael Barker found a bug, which is either caused by the different OS used or the different compiler used (Windows vs. Linux/Mac, or Eclipse vs. Sun/Apple compiler). [...]
Michael Barker
Okay, figured it out. It is caused by the eclipse compiler. It generates slightly different bytecode for the foreach loop to the sun compiler. I.e. with the eclipse compiler it does not trigger local variable declarations, therefore when searchMember is called on the LocalVariableMapper, it can't "see" the generated variables. I can work around this. As I figure out the code I will try to put together a patch. Mike
Avah
There was an issue with "foreach" style loops when nested. The problem was that the compiled iterators (i$, usually) had the same name in different scopes, something I did not anticipate. That bug was fixed, but there might be others. You might be interested in the previous one's details here. If you're already debugging (and thank you very much for that!), try to verify it happens in normal, non-nested loops as well. It really narrows the problem down.
Michael Barker
It seems to be related to foreach style for loop. I changed it too a started for loop using a index int and it worked. I'm going to continue debugging.
Avah
Since I didn't get the chance of debugging into it yet (apparently it's an OS issue of some sort), would you say that it's a matter of nested loops or any loops? The idea for a google group is a good one. I'll start one and post about it soon.
Michael Barker
Hi, I am really interested in using this tool. I am running into the error mentioned in the first blog post using the code from SVN. It seems to struggle with yields within loops. Would you consider creating a google group for discussions around Yielder? Mike.
Hanson Char
>it worked when I ran it with the junit test I meant when I ran it with the junit test from within Eclipse 3.1.2.
Hanson Char
The JUnit didn't work and that's what motivated me to put in a simple main method in the 1st place. I tried the javaagent:yielder-0.1.1.jar=debug, it didn't make a difference on the command line, but it worked when I ran it with the junit test. The complete output is pretty verbose. I can post it here, but probably less of a nuisance if I emailed to you, but I don't know your email address. So just post an fragment below. Hope that helps. // class version 49.0 (49) // access flags 48 // signature Lcom/infomancers/collections/yield/Yielder; // declaration: com/infomancers/tests/YielderTests$3 extends com.infomancers.collections.yield.Yielder final class com/infomancers/tests/YielderTests$3 extends com/infomancers/collections/yield/Yielder { // compiled from: YielderTests.java OUTERCLASS com/infomancers/tests/YielderTests someStrings ()V // access flags 18 private final INNERCLASS com/infomancers/tests/YielderTests$3 null null // access flags 4112 final Lcom/infomancers/tests/YielderTests; this$0 // access flags 0 (Lcom/infomancers/tests/YielderTests;)V L0 LINENUMBER 1 L0 ALOAD 0 ALOAD 1 PUTFIELD com/infomancers/tests/YielderTests$3.this$0 : Lcom/infomancers/tests/YielderTests; L1 LINENUMBER 71 L1 ALOAD 0 INVOKESPECIAL com/infomancers/collections/yield/Yielder. ()V RETURN L2 LOCALVARIABLE this Lcom/infomancers/tests/YielderTests$3; L0 L2 0 MAXSTACK = 2 MAXLOCALS = 2 // access flags 4 protected yieldNextCore()V L0 LINENUMBER 74 L0 ALOAD 0 LDC "This" INVOKEVIRTUAL com/infomancers/tests/YielderTests$3.yieldReturn (Ljava/lang/Object;)V L1 LINENUMBER 75 L1 ALOAD 0 LDC "Is" INVOKEVIRTUAL com/infomancers/tests/YielderTests$3.yieldReturn (Ljava/lang/Object;)V L2 LINENUMBER 76 L2 ALOAD 0 LDC "Great" INVOKEVIRTUAL com/infomancers/tests/YielderTests$3.yieldReturn (Ljava/lang/Object;)V L3 LINENUMBER 77 L3 RETURN L4 LOCALVARIABLE this Lcom/infomancers/tests/YielderTests$3; L0 L4 0 MAXSTACK = 2 MAXLOCALS = 1 } // class version 49.0 (49) // access flags 48 // signature Lcom/infomancers/collections/yield/Yielder; // declaration: com/infomancers/tests/YielderTests$3 extends com.infomancers.collections.yield.Yielder final class com/infomancers/tests/YielderTests$3 extends com/infomancers/collections/yield/Yielder { // compiled from: YielderTests.java OUTERCLASS com/infomancers/tests/YielderTests someStrings ()V // access flags 18 private final INNERCLASS com/infomancers/tests/YielderTests$3 null null // access flags 4112 final Lcom/infomancers/tests/YielderTests; this$0 // access flags 0 (Lcom/infomancers/tests/YielderTests;)V L0 LINENUMBER 1 L0 ALOAD 0 ALOAD 1 PUTFIELD com/infomancers/tests/YielderTests$3.this$0 : Lcom/infomancers/tests/YielderTests; L1 LINENUMBER 71 L1 ALOAD 0 INVOKESPECIAL com/infomancers/collections/yield/Yielder. ()V RETURN L2 LOCALVARIABLE this Lcom/infomancers/tests/YielderTests$3; L0 L2 0 MAXSTACK = 2 MAXLOCALS = 2 // access flags 4 protected yieldNextCore()V ALOAD 0 GETFIELD com/infomancers/tests/YielderTests$3.state : B TABLESWITCH 1: L0 2: L1 3: L2 default: L3 L3 L4 LINENUMBER 74 L4 ALOAD 0 LDC "This" INVOKEVIRTUAL com/infomancers/tests/YielderTests$3.yieldReturn (Ljava/lang/Object;)V ALOAD 0 BIPUSH 1 PUTFIELD com/infomancers/tests/YielderTests$3.state : B RETURN L0 L5 LINENUMBER 75 L5 ALOAD 0 LDC "Is" INVOKEVIRTUAL com/infomancers/tests/YielderTests$3.yieldReturn (Ljava/lang/Object;)V ALOAD 0 BIPUSH 2 PUTFIELD com/infomancers/tests/YielderTests$3.state : B RETURN L1 L6 LINENUMBER 76 L6 ALOAD 0 LDC "Great" INVOKEVIRTUAL com/infomancers/tests/YielderTests$3.yieldReturn (Ljava/lang/Object;)V ALOAD 0 BIPUSH 3 PUTFIELD com/infomancers/tests/YielderTests$3.state : B RETURN L2 L7 LINENUMBER 77 L7 RETURN L8 LOCALVARIABLE this Lcom/infomancers/tests/YielderTests$3; L4 L8 0 MAXSTACK = 2 MAXLOCALS = 1 // access flags 2 // signature Lcom/infomancers/tests/YielderTests$3; // declaration: com.infomancers.tests.YielderTests$3 private Lcom/infomancers/tests/YielderTests$3; this$promoted$0$4 // access flags 2 // signature B // declaration: byte private B state } java.util.NoSuchElementException at java.util.LinkedList.remove(LinkedList.java:788) at java.util.LinkedList.removeFirst(LinkedList.java:134) at java.util.LinkedList.remove(LinkedList.java:481) at com.infomancers.collections.yield.asm.LocalVariablePromoter$MyMethodAdapter.dealWithLoads(LocalVariablePromoter.java:125) at com.infomancers.collections.yield.asm.LocalVariablePromoter$MyMethodAdapter.visitLabel(LocalVariablePromoter.java:103) at org.objectweb.asm.ClassReader.accept(Unknown Source) at org.objectweb.asm.ClassReader.accept(Unknown Source) at com.infomancers.collections.yield.asm.YielderTransformer.enhanceClass(YielderTransformer.java:112) at com.infomancers.collections.yield.asm.YielderTransformer.transform(YielderTransformer.java:88) at sun.instrument.TransformerManager.transform(TransformerManager.java:169) at sun.instrument.InstrumentationImpl.transform(InstrumentationImpl.java:365) at java.lang.ClassLoader.defineClass1(Native Method) at java.lang.ClassLoader.defineClass(ClassLoader.java:620) at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:124) at java.net.URLClassLoader.defineClass(URLClassLoader.java:260) at java.net.URLClassLoader.access$000(URLClassLoader.java:56) at java.net.URLClassLoader$1.run(URLClassLoader.java:195) at java.security.AccessController.doPrivileged(Native Method) at java.net.URLClassLoader.findClass(URLClassLoader.java:188) at java.lang.ClassLoader.loadClass(ClassLoader.java:306) at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:276) at java.lang.ClassLoader.loadClass(ClassLoader.java:251) at java.lang.ClassLoader.loadClassInternal(ClassLoader.java:319) at com.infomancers.tests.YielderTests.someStrings(YielderTests.java:71) 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.internal.runners.TestMethodRunner.executeMethodBody(TestMethodRunner.java:99) at org.junit.internal.runners.TestMethodRunner.runUnprotected(TestMethodRunner.java:81) at org.junit.internal.runners.BeforeAndAfterRunner.runProtected(BeforeAndAfterRunner.java:34) at org.junit.internal.runners.TestMethodRunner.runMethod(TestMethodRunner.java:75) at org.junit.internal.runners.TestMethodRunner.run(TestMethodRunner.java:45) at org.junit.internal.runners.TestClassMethodsRunner.invokeTestMethod(TestClassMethodsRunner.java:71) at org.junit.internal.runners.TestClassMethodsRunner.run(TestClassMethodsRunner.java:35) at org.junit.internal.runners.TestClassRunner$1.runUnprotected(TestClassRunner.java:42)// class version 49.0 (49)
Avah
Whoa! Did the JUnit itself work (after configuring it to run with the agent?) Also, can you please try to run it using -javaagent:yielder-0.1.1.jar=debug? it will output the bytecode (before and after the manipulation) and it will make it easier to debug.
Hanson Char
I added a main method to YielderTests.java: public static void main(String... args) { new YielderTests().list(); } And tried: java -cp "./yielder-0.1.1.jar;lib/junit-4.1.jar;lib/asm-all-3.0.jar;./bin" -javaagent:./yielder-0.1.1.jar com.infomancers.tests.YielderTests I got: java.lang.IllegalStateException: Local variable encountered with no member mapped to it at com.infomancers.collections.yield.asm.LocalVariablePromoter$MyMethodAdapter.searchMember(LocalVariablePromoter.java:162) at com.infomancers.collections.yield.asm.LocalVariablePromoter$MyMethodAdapter.visitVarInsn(LocalVariablePromoter.java:145) at org.objectweb.asm.ClassReader.accept(Unknown Source) at org.objectweb.asm.ClassReader.accept(Unknown Source) at com.infomancers.collections.yield.asm.YielderTransformer.enhanceClass(YielderTransformer.java:112) at com.infomancers.collections.yield.asm.YielderTransformer.transform(YielderTransformer.java:88) at sun.instrument.TransformerManager.transform(TransformerManager.java:169) at sun.instrument.InstrumentationImpl.transform(InstrumentationImpl.java:365) at java.lang.ClassLoader.defineClass1(Native Method) at java.lang.ClassLoader.defineClass(ClassLoader.java:620) at java.security.SecureClassLoader.defineClass(SecureClassLoader.java:124) at java.net.URLClassLoader.defineClass(URLClassLoader.java:260) at java.net.URLClassLoader.access$000(URLClassLoader.java:56) at java.net.URLClassLoader$1.run(URLClassLoader.java:195) at java.security.AccessController.doPrivileged(Native Method) at java.net.URLClassLoader.findClass(URLClassLoader.java:188) at java.lang.ClassLoader.loadClass(ClassLoader.java:306) at sun.misc.Launcher$AppClassLoader.loadClass(Launcher.java:276) at java.lang.ClassLoader.loadClass(ClassLoader.java:251) at java.lang.ClassLoader.loadClassInternal(ClassLoader.java:319) at com.infomancers.tests.YielderTests.list(YielderTests.java:46) at com.infomancers.tests.YielderTests.main(YielderTests.java:230) Exception in thread "main" junit.framework.AssertionFailedError: Element 0 not equal! expected: but was: at junit.framework.Assert.fail(Assert.java:47) at junit.framework.Assert.failNotEquals(Assert.java:277) at junit.framework.Assert.assertEquals(Assert.java:64) at com.infomancers.tests.YielderTests.list(YielderTests.java:61) at com.infomancers.tests.YielderTests.main(YielderTests.java:230) I am using: java version "1.6.0_01" Java(TM) SE Runtime Environment (build 1.6.0_01-b06) Java HotSpot(TM) Client VM (build 1.6.0_01-b06, mixed mode, sharing) Any idea ?