groovy
  1. groovy
  2. GROOVY-5385

StackOverflow Exception when calling super.method, which returns an instance of the corresponding class.

    Details

    • Type: Bug Bug
    • Status: Closed Closed
    • Priority: Major Major
    • Resolution: Fixed
    • Affects Version/s: 1.7.10, 2.0-beta-2, 1.8.6
    • Fix Version/s: 2.2.1, 2.1.10
    • Component/s: groovy-jdk
    • Labels:
      None
    • Environment:
      Windows 7, IntelliJ IDEA
    • Number of attachments :
      1

      Description

      You get a StackOverflow Exception when running following code:

      A.groovy
      abstract class A {
          A attach(){
              System.out.println( "A does something else");
              return this;
          }
      }
      
      B.groovy
      class B extends A {
          @Override
          B attach(){
              System.out.println("B does something else");
              return (B) super.attach();
          }
      }
      
      C.groovy
      class C extends B {
          @Override
          C attach(){
              System.out.println("C does something else");
              return (C) super.attach();
          }
      }
      
      Test.groovy
      C c = new C(); c.attach();
      

      This bug only occurs when the depth of the class hierarchy exceeds two classes.
      Moreover this bug seems depend on the method name! If you try attachMe() as method name the Stackoverflow Exception won't be raised.
      The whole ErrorOutput can be found attached.

      Error.output
      C does something else
      C does something else
      C does something else
      C does something else
      Exception in thread "main" java.lang.StackOverflowError
      	at groovy.lang.MetaClassImpl.getMetaProperty(MetaClassImpl.java:2441)
      	at groovy.lang.MetaClassImpl.getMetaProperty(MetaClassImpl.java:2415)
      	at groovy.lang.MetaClassImpl.getProperty(MetaClassImpl.java:1510)
      	at groovy.lang.MetaClassImpl.getProperty(MetaClassImpl.java:3308)
      	at org.codehaus.groovy.runtime.callsite.ClassMetaClassGetPropertySite.getProperty(ClassMetaClassGetPropertySite.java:48)
      	at org.codehaus.groovy.runtime.callsite.AbstractCallSite.callGetProperty(AbstractCallSite.java:227)
      	at C.attach(C.groovy:20)
      	at C.attach(C.groovy)
      	at B.attach(B.groovy)
      	at C.super$3$attach(C.groovy)
      	at sun.reflect.GeneratedMethodAccessor1.invoke(Unknown Source)
      	at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:25)
      	at java.lang.reflect.Method.invoke(Method.java:597)
      	at org.codehaus.groovy.reflection.CachedMethod.invoke(CachedMethod.java:90)
      	at groovy.lang.MetaMethod.doMethodInvoke(MetaMethod.java:233)
      	at groovy.lang.MetaClassImpl.invokeMethod(MetaClassImpl.java:1047)
      	at org.codehaus.groovy.runtime.ScriptBytecodeAdapter.invokeMethodOnSuperN(ScriptBytecodeAdapter.java:128)
      	at org.codehaus.groovy.runtime.ScriptBytecodeAdapter.invokeMethodOnSuper0(ScriptBytecodeAdapter.java:148)
      
      1. erroroutput.txt
        67 kB
        Stefan Leonhartsberger

        Activity

        Hide
        Paul King added a comment -

        Had a quick look at this. Groovy is creating bridge methods for each covariant return type, e.g. for class C, the methods "A attach()", "B attach()" are added in addition to the one in the class itself, i.e. "C attach()". Depending on the order these are placed in the file, you will get strange behaviour. The workaround is to have A as your return type everywhere for the "attach" method.

        Show
        Paul King added a comment - Had a quick look at this. Groovy is creating bridge methods for each covariant return type, e.g. for class C, the methods "A attach()", "B attach()" are added in addition to the one in the class itself, i.e. "C attach()". Depending on the order these are placed in the file, you will get strange behaviour. The workaround is to have A as your return type everywhere for the "attach" method.
        Hide
        Stefan Leonhartsberger added a comment -

        Thank you for the reply.
        We already make use of this workaround. Nevertheless we do not want to force the users of our classes to work with explicit casts everytime.
        Will this one be fixed?

        Show
        Stefan Leonhartsberger added a comment - Thank you for the reply. We already make use of this workaround. Nevertheless we do not want to force the users of our classes to work with explicit casts everytime. Will this one be fixed?
        Hide
        Paul King added a comment -

        Yes, the intention is to fix it - it may overlap with GROOVY-5352, so fixing one might fix the other if we do the fix right.

        Show
        Paul King added a comment - Yes, the intention is to fix it - it may overlap with GROOVY-5352 , so fixing one might fix the other if we do the fix right.
        Hide
        blackdrag blackdrag added a comment -

        I compared with Java and Java also creates those two bridge methods. So it must be something else.

        Show
        blackdrag blackdrag added a comment - I compared with Java and Java also creates those two bridge methods. So it must be something else.
        Hide
        blackdrag blackdrag added a comment -

        looking at this more the problem is the following: C.super$3$attach does INVOKESPECIAL B.attach ()LA; and B.attach()LA; is correctly doing an invokevirtual for attach, which will pick up the version of C. The super$3$attach method has instead to invoke B.attach()LB;, never the bridge method. Then the stack overflow will not happen

        Show
        blackdrag blackdrag added a comment - looking at this more the problem is the following: C.super$3$attach does INVOKESPECIAL B.attach ()LA; and B.attach()LA; is correctly doing an invokevirtual for attach, which will pick up the version of C. The super$3$attach method has instead to invoke B.attach()LB;, never the bridge method. Then the stack overflow will not happen
        Hide
        blackdrag blackdrag added a comment -

        fixed

        Show
        blackdrag blackdrag added a comment - fixed
        Hide
        Romaric Philogene added a comment -

        Hi guys,

        I have exactly the same issue by using Groovy 2.2.2..

        Show
        Romaric Philogene added a comment - Hi guys, I have exactly the same issue by using Groovy 2.2.2..

          People

          • Assignee:
            blackdrag blackdrag
            Reporter:
            Stefan Leonhartsberger
          • Votes:
            2 Vote for this issue
            Watchers:
            7 Start watching this issue

            Dates

            • Created:
              Updated:
              Resolved: