batman
batman

Reputation: 4928

How Closures are executed?

I'm very new to Groovy. I wonder how Closures are implemented in Groovy.

Lets say :

def a = { println "Hello" }
a()

when a() is done, what is actually happening behind the scenes? Which method does a() calls to make the closure executable?

Thanks in advance.

Upvotes: 4

Views: 2533

Answers (2)

Xeon
Xeon

Reputation: 5989

Basically:

  • your closure is a class with specific name
  • a() invokes doCall() which invokes doCall(Object it) (implicit it in closures)
  • acallsite contains method names (2 x println) - and are invoked with appropriate arguments

Here you go:

For this Groovy Script:

def a = { println "Hello"; println "Hello2" }
a()

Closure a looks like this:

class Test$_run_closure1 extends Closure
implements GeneratedClosure
{

    public Object doCall(Object it)
    {
        CallSite acallsite[] = $getCallSiteArray();
        acallsite[0].callCurrent(this, "Hello");
        return acallsite[1].callCurrent(this, "Hello2");
    }

    public Object doCall()
    {
        CallSite acallsite[] = $getCallSiteArray();
        return doCall(null);
    }

    protected MetaClass $getStaticMetaClass()
    {
        if(getClass() != Test$_run_closure1)
            return ScriptBytecodeAdapter.initMetaClass(this);
        ClassInfo classinfo = $staticClassInfo;
        if(classinfo == null)
            $staticClassInfo = classinfo = ClassInfo.getClassInfo(getClass());
        return classinfo.getMetaClass();
    }

    public static void __$swapInit()
    {
        CallSite acallsite[] = $getCallSiteArray();
        $callSiteArray = null;
    }

    private static void $createCallSiteArray_1(String as[])
    {
        as[0] = "println";
        as[1] = "println";
    }

    private static CallSiteArray $createCallSiteArray()
    {
        String as[] = new String[2];
        $createCallSiteArray_1(as);
        return new CallSiteArray(Test$_run_closure1, as);
    }

    private static CallSite[] $getCallSiteArray()
    {
        CallSiteArray callsitearray;
        if($callSiteArray == null || (callsitearray = (CallSiteArray)$callSiteArray.get()) == null)
        {
            callsitearray = $createCallSiteArray();
            $callSiteArray = new SoftReference(callsitearray);
        }
        return callsitearray.array;
    }

    static Class _mthclass$(String s)
    {
        try
        {
            return Class.forName(s);
        }
        catch(ClassNotFoundException classnotfoundexception)
        {
            throw new NoClassDefFoundError(classnotfoundexception.getMessage());
        }
    }

    private static ClassInfo $staticClassInfo;
    public static transient boolean __$stMC;
    private static SoftReference $callSiteArray;

    static 
    {
        __$swapInit();
    }

    public Test$_run_closure1(Object _outerInstance, Object _thisObject)
    {
        CallSite acallsite[] = $getCallSiteArray();
        super(_outerInstance, _thisObject);
    }
}

Upvotes: 6

tim_yates
tim_yates

Reputation: 171184

It ends up calling one of the Closure.call methods (in this case the one with no args)

There's more info about this in the documentation

Upvotes: 4

Related Questions