Sidebar LogoHomeIndexIndexGitHub </> Back Next Side steps

Side steps


Intermediate Java code introspection

Groovy docs look unfriendly in that they show us the generated intermediate Java class examples, like [groovy_site, exact point], but give us no easy way to see the same about our own Groovy scripts. Here are some possible reasons:

Here's the workaround we are going to use:

CFR Java decompiler:

Here's a short example. Groovy generated class file methods.class is going to be decompiled:

>set CFR_HOME=directory\where\cfr-0.152.jar\is_located\

>java -jar %CFR_HOME%cfr-0.152.jar methods.class > methods.java

> del methods.class

Here are the most interesting fragments of the result:

project1/methods.java
/*
 * Decompiled with CFR 0.152.
 * 
 * Could not load the following classes:
 *  groovy.lang.Binding
 *  groovy.lang.MetaClass
 *  groovy.lang.Script
...
*/
import groovy.lang.Binding;
import groovy.lang.MetaClass;
import groovy.lang.Script;
...
public class methods
extends Script {
...
    public methods() {
    }

    public methods(Binding context) {
        super(context);
    }

    public static void main(String ... args) {
        IndyInterface.bootstrap("invoke", "runScript", 0, InvokerHelper.class, methods.class, args);
    }

    public Object run() {
        IndyInterface.bootstrap("invoke", "println", 2, this, IndyInterface.bootstrap("invoke", "sum", 2, this, 7, 4));
        return IndyInterface.bootstrap("invoke", "println", 2, this, IndyInterface.bootstrap("invoke", "sum", 2, this, 7));
    }

    public Object sum(int a, int b) {
        return IndyInterface.bootstrap("invoke", "plus", 0, a, b);
    }
...
}

Additional considerations

Our script may create multiple classes, like with closures:

In such cases we may want to decompile all of them in one go:

java -jar cfr-0.152.jar *.class

See the output of:

to know how to specify the input and output directories for better code organization.

Also see the following options to control the decompilation process:

--hidebridgemethods true --innerclasses false --decodelambdas false --comments false

Here are explanations given by Chat GPT [chat_gpt]:


Running by Java runtime

As it's shown above Groovy compiler can compile a normal Java class file. Starting from Groovy 3.0+, compiled script classes include a generated public static void main(String... args) method, so it may be executed by a Java runtime. Still Groovy runtime JARs (groovy-*.jar) need to be added to the class path:

>type hello_world.groovy
println "Hello world!"

>groovyc hello_world.groovy

>dir /b | find "hello_world.class"
hello_world.class

>java -cp ".;%GROOVY_HOME%\lib\*" hello_world
Hello world!

>del hello_world.class

The GROOVY_HOME environment variable should point to the Groovy installation directory (or the certain path may be used).

 


Back Next