ReplaceMethodCallsAdapterpublic class ReplaceMethodCallsAdapter extends org.objectweb.asm.ClassVisitor Replaces calls to certain methods that do not exist in the Desktop VM. Useful for methods in the
"java" package. |
Fields Summary |
---|
private static Set | ARRAYCOPY_DESCRIPTORSDescriptors for specialized versions {@link System#arraycopy} that are not present on the
Desktop VM. | private static final List | METHOD_REPLACERS | private static final String | ANDROID_LOCALE_CLASS | private static final String | JAVA_LOCALE_CLASS | private static final org.objectweb.asm.Type | STRING | private static final String | JAVA_LANG_SYSTEM |
Methods Summary |
---|
public static boolean | isReplacementNeeded(java.lang.String owner, java.lang.String name, java.lang.String desc)
// Static initialization block to initialize METHOD_REPLACERS.
// Case 1: java.lang.System.arraycopy()
METHOD_REPLACERS.add(new MethodReplacer() {
@Override
public boolean isNeeded(String owner, String name, String desc) {
return JAVA_LANG_SYSTEM.equals(owner) && "arraycopy".equals(name) &&
ARRAYCOPY_DESCRIPTORS.contains(desc);
}
@Override
public void replace(MethodInformation mi) {
assert isNeeded(mi.owner, mi.name, mi.desc);
mi.desc = "(Ljava/lang/Object;ILjava/lang/Object;II)V";
}
});
// Case 2: java.util.Locale.toLanguageTag() and java.util.Locale.getScript()
METHOD_REPLACERS.add(new MethodReplacer() {
private final String LOCALE_TO_STRING =
Type.getMethodDescriptor(STRING, Type.getType(Locale.class));
@Override
public boolean isNeeded(String owner, String name, String desc) {
return JAVA_LOCALE_CLASS.equals(owner) && "()Ljava/lang/String;".equals(desc) &&
("toLanguageTag".equals(name) || "getScript".equals(name));
}
@Override
public void replace(MethodInformation mi) {
assert isNeeded(mi.owner, mi.name, mi.desc);
mi.opcode = Opcodes.INVOKESTATIC;
mi.owner = ANDROID_LOCALE_CLASS;
mi.desc = LOCALE_TO_STRING;
}
});
// Case 3: java.util.Locale.adjustLanguageCode() or java.util.Locale.forLanguageTag()
METHOD_REPLACERS.add(new MethodReplacer() {
private final String STRING_TO_STRING = Type.getMethodDescriptor(STRING, STRING);
private final String STRING_TO_LOCALE = Type.getMethodDescriptor(
Type.getType(Locale.class), STRING);
@Override
public boolean isNeeded(String owner, String name, String desc) {
return JAVA_LOCALE_CLASS.equals(owner) &&
("adjustLanguageCode".equals(name) && desc.equals(STRING_TO_STRING) ||
"forLanguageTag".equals(name) && desc.equals(STRING_TO_LOCALE));
}
@Override
public void replace(MethodInformation mi) {
assert isNeeded(mi.owner, mi.name, mi.desc);
mi.owner = ANDROID_LOCALE_CLASS;
}
});
// Case 4: java.lang.System.log?()
METHOD_REPLACERS.add(new MethodReplacer() {
@Override
public boolean isNeeded(String owner, String name, String desc) {
return JAVA_LANG_SYSTEM.equals(owner) && name.length() == 4
&& name.startsWith("log");
}
@Override
public void replace(MethodInformation mi) {
assert isNeeded(mi.owner, mi.name, mi.desc);
assert mi.desc.equals("(Ljava/lang/String;Ljava/lang/Throwable;)V")
|| mi.desc.equals("(Ljava/lang/String;)V");
mi.name = "log";
mi.owner = Type.getInternalName(System_Delegate.class);
}
});
// Case 5: java.util.LinkedHashMap.eldest()
METHOD_REPLACERS.add(new MethodReplacer() {
private final String VOID_TO_MAP_ENTRY =
Type.getMethodDescriptor(Type.getType(Map.Entry.class));
private final String LINKED_HASH_MAP = Type.getInternalName(LinkedHashMap.class);
@Override
public boolean isNeeded(String owner, String name, String desc) {
return LINKED_HASH_MAP.equals(owner) &&
"eldest".equals(name) &&
VOID_TO_MAP_ENTRY.equals(desc);
}
@Override
public void replace(MethodInformation mi) {
assert isNeeded(mi.owner, mi.name, mi.desc);
mi.opcode = Opcodes.INVOKESTATIC;
mi.owner = Type.getInternalName(LinkedHashMap_Delegate.class);
mi.desc = Type.getMethodDescriptor(
Type.getType(Map.Entry.class), Type.getType(LinkedHashMap.class));
}
});
for (MethodReplacer replacer : METHOD_REPLACERS) {
if (replacer.isNeeded(owner, name, desc)) {
return true;
}
}
return false;
| public org.objectweb.asm.MethodVisitor | visitMethod(int access, java.lang.String name, java.lang.String desc, java.lang.String signature, java.lang.String[] exceptions)
return new MyMethodVisitor(super.visitMethod(access, name, desc, signature, exceptions));
|
|