What is Java Synthetic Class (ACC_SYNTHETIC)? with the example of BoundMethodHandle$1.class in Java package java.lang.invoke
When a
Binary Code is always the best document, so let's check an example: the BoundMethodHandle$1.class class in java.base.jmod in JDK.
The class file
.class
file marked with the ACC_SYNTHETIC flag, it indicates the .class
file was generated by compiler and does not appear in the corresponding .java
source code.Binary Code is always the best document, so let's check an example: the BoundMethodHandle$1.class class in java.base.jmod in JDK.
The class file
BoundMethodHandle$1.class
has been marked as synthetic flag, as shown bellow:Basic Information of BoundMethodHandle$1.class |
UML diagram of BoundMethodHandle$1.class |
And this class is used by the container class BoundMethodHandle:
Dependency Network diagram of BoundMethodHandle$1.class |
This class does not exist in the original source code BoundMethodHandle.java, but generated by the java compiler, from the following two (2) methods in the Java class BoundMethodHandle:
- BoundMethodHandle.bindSingle(), at byte code offset 0
- BoundMethodHandle.arg(), at byte code offset 17
Byte code of method BoundMethodHandle.bindSingle() |
Byte code of method BoundMethodHandle.arg() |
Highlight: Source code of
BoundMethodHandle.bindSingle()
:
62 static BoundMethodHandle bindSingle(MethodType type, LambdaForm form, BasicType xtype, Object x) {
63 // for some type signatures, there exist pre-defined concrete BMH classes
64 try {
65 switch (xtype) {
66 case L_TYPE:
67 return bindSingle(type, form, x); // Use known fast path.
68 case I_TYPE:
69 return (BoundMethodHandle) SPECIALIZER.topSpecies().extendWith(I_TYPE_NUM).factory().invokeBasic(type, form, ValueConversions.widenSubword(x));
70 case J_TYPE:
71 return (BoundMethodHandle) SPECIALIZER.topSpecies().extendWith(J_TYPE_NUM).factory().invokeBasic(type, form, (long) x);
72 case F_TYPE:
73 return (BoundMethodHandle) SPECIALIZER.topSpecies().extendWith(F_TYPE_NUM).factory().invokeBasic(type, form, (float) x);
74 case D_TYPE:
75 return (BoundMethodHandle) SPECIALIZER.topSpecies().extendWith(D_TYPE_NUM).factory().invokeBasic(type, form, (double) x);
76 default : throw newInternalError("unexpected xtype: " + xtype);
77 }
78 } catch (Throwable t) {
79 throw uncaughtException(t);
80 }
81 }
Highlight: Source code of
BoundMethodHandle.arg()
:
178 /*non-public*/ final Object arg(int i) {
179 try {
180 Class fieldType = speciesData().fieldTypes().get(i);
181 switch (BasicType.basicType(fieldType)) {
182 case L_TYPE: return speciesData().getter(i).invokeBasic(this);
183 case I_TYPE: return (int) speciesData().getter(i).invokeBasic(this);
184 case J_TYPE: return (long) speciesData().getter(i).invokeBasic(this);
185 case F_TYPE: return (float) speciesData().getter(i).invokeBasic(this);
186 case D_TYPE: return (double) speciesData().getter(i).invokeBasic(this);
187 }
188 } catch (Throwable ex) {
189 throw uncaughtException(ex);
190 }
191 throw new InternalError("unexpected type: " + speciesData().key()+"."+i);
192 }
So we can found that, the key reason for the compiler to generate the
BoundMethodHandle$1.class
class, and its $SwitchMap$java$lang$invoke$LambdaForm$BasicType field is, there is an switch statment on the LambdaForm.BasicType value.Here is the highlighted source code of the
LambdaForm.BasicType
:
139 enum BasicType {
140 L_TYPE('L', Object.class, Wrapper.OBJECT), // all reference types
141 I_TYPE('I', int.class, Wrapper.INT),
142 J_TYPE('J', long.class, Wrapper.LONG),
143 F_TYPE('F', float.class, Wrapper.FLOAT),
144 D_TYPE('D', double.class, Wrapper.DOUBLE), // all primitive types
145 V_TYPE('V', void.class, Wrapper.VOID); // not valid in all contexts
...
155 static final byte
156 L_TYPE_NUM = (byte) L_TYPE.ordinal(),
157 I_TYPE_NUM = (byte) I_TYPE.ordinal(),
158 J_TYPE_NUM = (byte) J_TYPE.ordinal(),
159 F_TYPE_NUM = (byte) F_TYPE.ordinal(),
160 D_TYPE_NUM = (byte) D_TYPE.ordinal(),
161 V_TYPE_NUM = (byte) V_TYPE.ordinal();
And we can easily double confirm it is indeed the source code for the generated class contructor logic of BoundMethodHandle$1.class.
Call graph of BoundMethodHandle$1.class class constructor |
Comments
Post a Comment