- 先写一个java代码
// ./java/MyClass.java
public class MyClass {
public int add() {
int a = 1;
int b = 2;
return a+b;
}
public static void main(String[] args) {
MyClass m = new MyClass();
System.out.println(m.add());
}
}
- 编译java源文件
javac MyClass.java
- 查看字节码
javap -c MyClass >MyClass.txt
输出
Compiled from "MyClass.java"
public class MyClass {
public MyClass();
Code:
0: aload_0
1: invokespecial #1 // Method java/lang/Object."<init>":()V
4: return
public int add();
Code:
0: iconst_1
1: istore_1
2: iconst_2
3: istore_2
4: iload_1
5: iload_2
6: iadd
7: ireturn
public static void main(java.lang.String[]);
Code:
0: new #7 // class MyClass
3: dup
4: invokespecial #9 // Method "<init>":()V
7: astore_1
8: getstatic #10 // Field java/lang/System.out:Ljava/io/PrintStream;
11: aload_1
12: invokevirtual #16 // Method add:()I
15: invokevirtual #20 // Method java/io/PrintStream.println:(I)V
18: return
}
- 直接将java源文件改成groovy
cp java/MyClass.java groovy/MyClass.groovy
- 编译groovy源文件
groovyc MyClass.groovy
- 查看字节码
javap -c MyClass >MyClass.txt
输出结果
Compiled from "MyClass.groovy"
public class MyClass implements groovy.lang.GroovyObject {
public static transient boolean __$stMC;
public MyClass();
Code:
0: nop
1: invokestatic #20 // Method $getCallSiteArray:()[Lorg/codehaus/groovy/runtime/callsite/CallSite;
4: astore_1
5: aload_0
6: invokespecial #22 // Method java/lang/Object."<init>":()V
9: aload_0
10: invokevirtual #26 // Method $getStaticMetaClass:()Lgroovy/lang/MetaClass;
13: astore_2
14: aload_2
15: aload_0
16: swap
17: putfield #28 // Field metaClass:Lgroovy/lang/MetaClass;
20: aload_2
21: pop
22: return
public int add();
Code:
0: nop
1: invokestatic #20 // Method $getCallSiteArray:()[Lorg/codehaus/groovy/runtime/callsite/CallSite;
4: astore_1
5: iconst_1
6: istore_2
7: iload_2
8: pop
9: iconst_2
10: istore_3
11: iload_3
12: pop
13: invokestatic #38 // Method org/codehaus/groovy/runtime/BytecodeInterface8.isOrigInt:()Z
16: ifeq 34
19: getstatic #40 // Field __$stMC:Z
22: ifne 34
25: invokestatic #43 // Method org/codehaus/groovy/runtime/BytecodeInterface8.disabledStandardMetaClass:()Z
28: ifne 34
31: goto 58
34: aload_1
35: ldc #44 // int 0
37: aaload
38: iload_2
39: invokestatic #50 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
42: iload_3
43: invokestatic #50 // Method java/lang/Integer.valueOf:(I)Ljava/lang/Integer;
46: invokeinterface #56, 3 // InterfaceMethod org/codehaus/groovy/runtime/callsite/CallSite.call:(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
51: invokestatic #62 // Method org/codehaus/groovy/runtime/typehandling/DefaultTypeTransformation.intUnbox:(Ljava/lang/Object;)I
54: ireturn
55: nop
56: nop
57: athrow
58: iload_2
59: iload_3
60: iadd
61: ireturn
public static void main(java.lang.String...);
Code:
0: nop
1: invokestatic #20 // Method $getCallSiteArray:()[Lorg/codehaus/groovy/runtime/callsite/CallSite;
4: astore_1
5: aload_1
6: ldc #72 // int 1
8: aaload
9: ldc #2 // class MyClass
11: invokeinterface #76, 2 // InterfaceMethod org/codehaus/groovy/runtime/callsite/CallSite.callConstructor:(Ljava/lang/Object;)Ljava/lang/Object;
16: ldc #2 // class MyClass
18: invokestatic #82 // Method org/codehaus/groovy/runtime/ScriptBytecodeAdapter.castToType:(Ljava/lang/Object;Ljava/lang/Class;)Ljava/lang/Object;
21: checkcast #2 // class MyClass
24: astore_2
25: aload_2
26: pop
27: aload_1
28: ldc #83 // int 2
30: aaload
31: aload_1
32: ldc #84 // int 3
34: aaload
35: ldc #86 // class java/lang/System
37: invokeinterface #89, 2 // InterfaceMethod org/codehaus/groovy/runtime/callsite/CallSite.callGetProperty:(Ljava/lang/Object;)Ljava/lang/Object;
42: aload_1
43: ldc #90 // int 4
45: aaload
46: aload_2
47: invokeinterface #92, 2 // InterfaceMethod org/codehaus/groovy/runtime/callsite/CallSite.call:(Ljava/lang/Object;)Ljava/lang/Object;
52: invokeinterface #56, 3 // InterfaceMethod org/codehaus/groovy/runtime/callsite/CallSite.call:(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;
57: pop
58: return
protected groovy.lang.MetaClass $getStaticMetaClass();
Code:
0: aload_0
1: invokevirtual #99 // Method java/lang/Object.getClass:()Ljava/lang/Class;
4: ldc #2 // class MyClass
6: if_acmpeq 14
9: aload_0
10: invokestatic #103 // Method org/codehaus/groovy/runtime/ScriptBytecodeAdapter.initMetaClass:(Ljava/lang/Object;)Lgroovy/lang/MetaClass;
13: areturn
14: getstatic #105 // Field $staticClassInfo:Lorg/codehaus/groovy/reflection/ClassInfo;
17: astore_1
18: aload_1
19: ifnonnull 34
22: aload_0
23: invokevirtual #99 // Method java/lang/Object.getClass:()Ljava/lang/Class;
26: invokestatic #111 // Method org/codehaus/groovy/reflection/ClassInfo.getClassInfo:(Ljava/lang/Class;)Lorg/codehaus/groovy/reflection/ClassInfo;
29: dup
30: astore_1
31: putstatic #105 // Field $staticClassInfo:Lorg/codehaus/groovy/reflection/ClassInfo;
34: aload_1
35: invokevirtual #114 // Method org/codehaus/groovy/reflection/ClassInfo.getMetaClass:()Lgroovy/lang/MetaClass;
38: areturn
public groovy.lang.MetaClass getMetaClass();
Code:
0: aload_0
1: getfield #28 // Field metaClass:Lgroovy/lang/MetaClass;
4: dup
5: ifnull 9
8: areturn
9: pop
10: aload_0
11: dup
12: invokevirtual #26 // Method $getStaticMetaClass:()Lgroovy/lang/MetaClass;
15: putfield #28 // Field metaClass:Lgroovy/lang/MetaClass;
18: aload_0
19: getfield #28 // Field metaClass:Lgroovy/lang/MetaClass;
22: areturn
public void setMetaClass(groovy.lang.MetaClass);
Code:
0: aload_0
1: aload_1
2: putfield #28 // Field metaClass:Lgroovy/lang/MetaClass;
5: return
}
- 反编译字节码
java -jar cfr-0.151.jar ./groovy/MyClass.class --outputpath ./groovy
输出结果
/*
* Decompiled with CFR 0.151.
*
* Could not load the following classes:
* groovy.lang.GroovyObject
* groovy.lang.MetaClass
* groovy.transform.Generated
* groovy.transform.Internal
* org.codehaus.groovy.reflection.ClassInfo
* org.codehaus.groovy.runtime.BytecodeInterface8
* org.codehaus.groovy.runtime.ScriptBytecodeAdapter
* org.codehaus.groovy.runtime.callsite.CallSite
* org.codehaus.groovy.runtime.callsite.CallSiteArray
* org.codehaus.groovy.runtime.typehandling.DefaultTypeTransformation
*/
import groovy.lang.GroovyObject;
import groovy.lang.MetaClass;
import groovy.transform.Generated;
import groovy.transform.Internal;
import java.beans.Transient;
import java.lang.ref.SoftReference;
import org.codehaus.groovy.reflection.ClassInfo;
import org.codehaus.groovy.runtime.BytecodeInterface8;
import org.codehaus.groovy.runtime.ScriptBytecodeAdapter;
import org.codehaus.groovy.runtime.callsite.CallSite;
import org.codehaus.groovy.runtime.callsite.CallSiteArray;
import org.codehaus.groovy.runtime.typehandling.DefaultTypeTransformation;
public class MyClass
implements GroovyObject {
private static /* synthetic */ ClassInfo $staticClassInfo;
public static transient /* synthetic */ boolean __$stMC;
private transient /* synthetic */ MetaClass metaClass;
private static /* synthetic */ SoftReference $callSiteArray;
@Generated
public MyClass() {
MetaClass metaClass;
CallSite[] callSiteArray = MyClass.$getCallSiteArray();
this.metaClass = metaClass = this.$getStaticMetaClass();
}
public int add() {
CallSite[] callSiteArray = MyClass.$getCallSiteArray();
int a = 1;
int b = 2;
if (!BytecodeInterface8.isOrigInt() || __$stMC || BytecodeInterface8.disabledStandardMetaClass()) {
return DefaultTypeTransformation.intUnbox((Object)callSiteArray[0].call((Object)a, (Object)b));
}
return a + b;
}
public static void main(String ... args) {
CallSite[] callSiteArray = MyClass.$getCallSiteArray();
MyClass m = (MyClass)ScriptBytecodeAdapter.castToType((Object)callSiteArray[1].callConstructor(MyClass.class), MyClass.class);
callSiteArray[2].call(callSiteArray[3].callGetProperty(System.class), callSiteArray[4].call((Object)m));
}
protected /* synthetic */ MetaClass $getStaticMetaClass() {
if (this.getClass() != MyClass.class) {
return ScriptBytecodeAdapter.initMetaClass((Object)this);
}
ClassInfo classInfo = $staticClassInfo;
if (classInfo == null) {
$staticClassInfo = classInfo = ClassInfo.getClassInfo(this.getClass());
}
return classInfo.getMetaClass();
}
@Generated
@Internal
@Transient
public MetaClass getMetaClass() {
MetaClass metaClass = this.metaClass;
if (metaClass != null) {
return metaClass;
}
this.metaClass = this.$getStaticMetaClass();
return this.metaClass;
}
@Generated
@Internal
public void setMetaClass(MetaClass metaClass) {
this.metaClass = metaClass;
}
private static /* synthetic */ void $createCallSiteArray_1(String[] stringArray) {
stringArray[0] = "plus";
stringArray[1] = "<$constructor$>";
stringArray[2] = "println";
stringArray[3] = "out";
stringArray[4] = "add";
}
private static /* synthetic */ CallSiteArray $createCallSiteArray() {
String[] stringArray = new String[5];
MyClass.$createCallSiteArray_1(stringArray);
return new CallSiteArray(MyClass.class, stringArray);
}
private static /* synthetic */ CallSite[] $getCallSiteArray() {
CallSiteArray callSiteArray;
if ($callSiteArray == null || (callSiteArray = (CallSiteArray)$callSiteArray.get()) == null) {
callSiteArray = MyClass.$createCallSiteArray();
$callSiteArray = new SoftReference<CallSiteArray>(callSiteArray);
}
return callSiteArray.array;
}
}
GroovyObject源码
package groovy.lang;
import groovy.transform.Internal;
/**
* The interface implemented by all Groovy objects.
* <p>
* Especially handy for using Groovy objects when in the Java world.
*/
public interface GroovyObject {
/**
* Invokes the given method.
*
* @param name the name of the method to call
* @param args the arguments to use for the method call
* @return the result of invoking the method
*/
@Internal // marked as internal just for backward compatibility, e.g. AbstractCallSite.createGroovyObjectGetPropertySite will check `isMarkedInternal`
default Object invokeMethod(String name, Object args) {
return getMetaClass().invokeMethod(this, name, args);
}
/**
* Retrieves a property value.
*
* @param propertyName the name of the property of interest
* @return the given property
*/
@Internal // marked as internal just for backward compatibility, e.g. AbstractCallSite.createGroovyObjectGetPropertySite will check `isMarkedInternal`
default Object getProperty(String propertyName) {
return getMetaClass().getProperty(this, propertyName);
}
/**
* Sets the given property to the new value.
*
* @param propertyName the name of the property of interest
* @param newValue the new value for the property
*/
@Internal // marked as internal just for backward compatibility, e.g. AbstractCallSite.createGroovyObjectGetPropertySite will check `isMarkedInternal`
default void setProperty(String propertyName, Object newValue) {
getMetaClass().setProperty(this, propertyName, newValue);
}
/**
* Returns the metaclass for a given class.
*
* @return the metaClass of this instance
*/
MetaClass getMetaClass();
/**
* Allows the MetaClass to be replaced with a derived implementation.
*
* @param metaClass the new metaclass
*/
void setMetaClass(MetaClass metaClass);
}
- 分析