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?
August 14th, 2007 at 9:20 am
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 ?
August 14th, 2007 at 9:36 am
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.
August 14th, 2007 at 7:35 pm
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)
August 14th, 2007 at 7:37 pm
>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.
August 18th, 2007 at 7:08 pm
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.
August 18th, 2007 at 8:15 pm
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.
August 18th, 2007 at 8:58 pm
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.
August 18th, 2007 at 9:03 pm
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.
August 18th, 2007 at 11:16 pm
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
August 19th, 2007 at 5:38 am
Wow, thanks! Can you describe the bug in the issues section of the project?
August 19th, 2007 at 6:06 am
[...] 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). [...]