📄 fieldtransformer.java
字号:
code.growStack(Descriptor.dataSize(finfo.getDescriptor()) - 1);
// *load_1
addTypeDependDataLoad(code, finfo.getDescriptor(), 1);
// invokeinterface // callback.write*(..)
addInvokeFieldHandlerMethod(classfile, code, finfo.getDescriptor(),
false);
// putfield // new value of the field
code.addOpcode(Opcode.PUTFIELD);
code.addIndex(base_field_index);
code.growStack(-Descriptor.dataSize(finfo.getDescriptor()));
// return
code.addOpcode(Opcode.RETURN);
minfo.setCodeAttribute(code.toCodeAttribute());
minfo.setAccessFlags(AccessFlag.PUBLIC);
classfile.addMethod(minfo);
}
private void transformInvokevirtualsIntoPutAndGetfields(ClassFile classfile)
throws CannotCompileException {
List methods = classfile.getMethods();
for (Iterator method_iter = methods.iterator(); method_iter.hasNext();) {
MethodInfo minfo = (MethodInfo) method_iter.next();
String methodName = minfo.getName();
if (methodName.startsWith(EACH_READ_METHOD_PREFIX)
|| methodName.startsWith(EACH_WRITE_METHOD_PREFIX)
|| methodName.equals(GETFIELDHANDLER_METHOD_NAME)
|| methodName.equals(SETFIELDHANDLER_METHOD_NAME)) {
continue;
}
CodeAttribute codeAttr = minfo.getCodeAttribute();
if (codeAttr == null) {
return;
}
CodeIterator iter = codeAttr.iterator();
while (iter.hasNext()) {
try {
int pos = iter.next();
pos = transformInvokevirtualsIntoGetfields(classfile, iter,
pos);
pos = transformInvokevirtualsIntoPutfields(classfile, iter,
pos);
} catch (BadBytecode e) {
throw new CannotCompileException(e);
}
}
}
}
private int transformInvokevirtualsIntoGetfields(ClassFile classfile,
CodeIterator iter, int pos) {
ConstPool cp = classfile.getConstPool();
int c = iter.byteAt(pos);
if (c != Opcode.GETFIELD) {
return pos;
}
int index = iter.u16bitAt(pos + 1);
String fieldName = cp.getFieldrefName(index);
String className = cp.getFieldrefClassName(index);
if ((!classfile.getName().equals(className))
|| (!readableFields.containsKey(fieldName))) {
return pos;
}
String desc = "()" + (String) readableFields.get(fieldName);
int read_method_index = cp.addMethodrefInfo(cp.getThisClassInfo(),
EACH_READ_METHOD_PREFIX + fieldName, desc);
iter.writeByte(Opcode.INVOKEVIRTUAL, pos);
iter.write16bit(read_method_index, pos + 1);
return pos;
}
private int transformInvokevirtualsIntoPutfields(ClassFile classfile,
CodeIterator iter, int pos) {
ConstPool cp = classfile.getConstPool();
int c = iter.byteAt(pos);
if (c != Opcode.PUTFIELD) {
return pos;
}
int index = iter.u16bitAt(pos + 1);
String fieldName = cp.getFieldrefName(index);
String className = cp.getFieldrefClassName(index);
if ((!classfile.getName().equals(className))
|| (!writableFields.containsKey(fieldName))) {
return pos;
}
String desc = "(" + (String) writableFields.get(fieldName) + ")V";
int write_method_index = cp.addMethodrefInfo(cp.getThisClassInfo(),
EACH_WRITE_METHOD_PREFIX + fieldName, desc);
iter.writeByte(Opcode.INVOKEVIRTUAL, pos);
iter.write16bit(write_method_index, pos + 1);
return pos;
}
private static void addInvokeFieldHandlerMethod(ClassFile classfile,
Bytecode code, String typeName, boolean isReadMethod) {
ConstPool cp = classfile.getConstPool();
// invokeinterface
int callback_type_index = cp.addClassInfo(FIELD_HANDLER_TYPE_NAME);
if ((typeName.charAt(0) == 'L')
&& (typeName.charAt(typeName.length() - 1) == ';')
|| (typeName.charAt(0) == '[')) {
// reference type
int indexOfL = typeName.indexOf('L');
String type;
if (indexOfL == 0) {
// not array
type = typeName.substring(1, typeName.length() - 1);
type = type.replace('/', '.');
} else if (indexOfL == -1) {
// array of primitive type
// do nothing
type = typeName;
} else {
// array of reference type
type = typeName.replace('/', '.');
}
if (isReadMethod) {
code
.addInvokeinterface(
callback_type_index,
"readObject",
"(Ljava/lang/Object;Ljava/lang/String;Ljava/lang/Object;)Ljava/lang/Object;",
4);
// checkcast
code.addCheckcast(type);
} else {
code
.addInvokeinterface(
callback_type_index,
"writeObject",
"(Ljava/lang/Object;Ljava/lang/String;Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;",
5);
// checkcast
code.addCheckcast(type);
}
} else if (typeName.equals("Z")) {
// boolean
if (isReadMethod) {
code.addInvokeinterface(callback_type_index, "readBoolean",
"(Ljava/lang/Object;Ljava/lang/String;Z)Z", 4);
} else {
code.addInvokeinterface(callback_type_index, "writeBoolean",
"(Ljava/lang/Object;Ljava/lang/String;ZZ)Z", 5);
}
} else if (typeName.equals("B")) {
// byte
if (isReadMethod) {
code.addInvokeinterface(callback_type_index, "readByte",
"(Ljava/lang/Object;Ljava/lang/String;B)B", 4);
} else {
code.addInvokeinterface(callback_type_index, "writeByte",
"(Ljava/lang/Object;Ljava/lang/String;BB)B", 5);
}
} else if (typeName.equals("C")) {
// char
if (isReadMethod) {
code.addInvokeinterface(callback_type_index, "readChar",
"(Ljava/lang/Object;Ljava/lang/String;C)C", 4);
} else {
code.addInvokeinterface(callback_type_index, "writeChar",
"(Ljava/lang/Object;Ljava/lang/String;CC)C", 5);
}
} else if (typeName.equals("I")) {
// int
if (isReadMethod) {
code.addInvokeinterface(callback_type_index, "readInt",
"(Ljava/lang/Object;Ljava/lang/String;I)I", 4);
} else {
code.addInvokeinterface(callback_type_index, "writeInt",
"(Ljava/lang/Object;Ljava/lang/String;II)I", 5);
}
} else if (typeName.equals("S")) {
// short
if (isReadMethod) {
code.addInvokeinterface(callback_type_index, "readShort",
"(Ljava/lang/Object;Ljava/lang/String;S)S", 4);
} else {
code.addInvokeinterface(callback_type_index, "writeShort",
"(Ljava/lang/Object;Ljava/lang/String;SS)S", 5);
}
} else if (typeName.equals("D")) {
// double
if (isReadMethod) {
code.addInvokeinterface(callback_type_index, "readDouble",
"(Ljava/lang/Object;Ljava/lang/String;D)D", 5);
} else {
code.addInvokeinterface(callback_type_index, "writeDouble",
"(Ljava/lang/Object;Ljava/lang/String;DD)D", 7);
}
} else if (typeName.equals("F")) {
// float
if (isReadMethod) {
code.addInvokeinterface(callback_type_index, "readFloat",
"(Ljava/lang/Object;Ljava/lang/String;F)F", 4);
} else {
code.addInvokeinterface(callback_type_index, "writeFloat",
"(Ljava/lang/Object;Ljava/lang/String;FF)F", 5);
}
} else if (typeName.equals("J")) {
// long
if (isReadMethod) {
code.addInvokeinterface(callback_type_index, "readLong",
"(Ljava/lang/Object;Ljava/lang/String;J)J", 5);
} else {
code.addInvokeinterface(callback_type_index, "writeLong",
"(Ljava/lang/Object;Ljava/lang/String;JJ)J", 7);
}
} else {
// bad type
throw new RuntimeException("bad type: " + typeName);
}
}
private static void addTypeDependDataLoad(Bytecode code, String typeName,
int i) {
if ((typeName.charAt(0) == 'L')
&& (typeName.charAt(typeName.length() - 1) == ';')
|| (typeName.charAt(0) == '[')) {
// reference type
code.addAload(i);
} else if (typeName.equals("Z") || typeName.equals("B")
|| typeName.equals("C") || typeName.equals("I")
|| typeName.equals("S")) {
// boolean, byte, char, int, short
code.addIload(i);
} else if (typeName.equals("D")) {
// double
code.addDload(i);
} else if (typeName.equals("F")) {
// float
code.addFload(i);
} else if (typeName.equals("J")) {
// long
code.addLload(i);
} else {
// bad type
throw new RuntimeException("bad type: " + typeName);
}
}
private static void addTypeDependDataStore(Bytecode code, String typeName,
int i) {
if ((typeName.charAt(0) == 'L')
&& (typeName.charAt(typeName.length() - 1) == ';')
|| (typeName.charAt(0) == '[')) {
// reference type
code.addAstore(i);
} else if (typeName.equals("Z") || typeName.equals("B")
|| typeName.equals("C") || typeName.equals("I")
|| typeName.equals("S")) {
// boolean, byte, char, int, short
code.addIstore(i);
} else if (typeName.equals("D")) {
// double
code.addDstore(i);
} else if (typeName.equals("F")) {
// float
code.addFstore(i);
} else if (typeName.equals("J")) {
// long
code.addLstore(i);
} else {
// bad type
throw new RuntimeException("bad type: " + typeName);
}
}
private static void addTypeDependDataReturn(Bytecode code, String typeName) {
if ((typeName.charAt(0) == 'L')
&& (typeName.charAt(typeName.length() - 1) == ';')
|| (typeName.charAt(0) == '[')) {
// reference type
code.addOpcode(Opcode.ARETURN);
} else if (typeName.equals("Z") || typeName.equals("B")
|| typeName.equals("C") || typeName.equals("I")
|| typeName.equals("S")) {
// boolean, byte, char, int, short
code.addOpcode(Opcode.IRETURN);
} else if (typeName.equals("D")) {
// double
code.addOpcode(Opcode.DRETURN);
} else if (typeName.equals("F")) {
// float
code.addOpcode(Opcode.FRETURN);
} else if (typeName.equals("J")) {
// long
code.addOpcode(Opcode.LRETURN);
} else {
// bad type
throw new RuntimeException("bad type: " + typeName);
}
}
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -