Aug 10

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?

  • Share/Bookmark

11 Responses to “Feedback regarding Java ‘yield’”

  1. Hanson Char Says:

    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 ?

  2. Avah Says:

    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.

  3. Hanson Char Says:

    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)

  4. Hanson Char Says:

    >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.

  5. Michael Barker Says:

    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.

  6. Avah Says:

    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.

  7. Michael Barker Says:

    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.

  8. Avah Says:

    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.

  9. Michael Barker Says:

    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

  10. Avah Says:

    Wow, thanks! Can you describe the bug in the issues section of the project?

  11. Chaotic Java » Yielder: Eclipse bug revealed, newsgroup created Says:

    [...] 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). [...]

Leave a Reply

Chaotic Java is Digg proof thanks to caching by WP Super Cache