@Patch
public void lockToSynchronized(CtBehavior ctBehavior, Map<String, String> attributes) throws BadBytecode {
CtClass ctClass = ctBehavior.getDeclaringClass();
MethodInfo methodInfo = ctBehavior.getMethodInfo();
CodeAttribute codeAttribute = methodInfo.getCodeAttribute();
CodeIterator iterator = codeAttribute.iterator();
ConstPool constPool = codeAttribute.getConstPool();
int done = 0;
while (iterator.hasNext()) {
int pos = iterator.next();
int op = iterator.byteAt(pos);
if (op == Opcode.INVOKEINTERFACE) {
int mref = iterator.u16bitAt(pos + 1);
if (constPool.getInterfaceMethodrefClassName(mref).endsWith("Lock")) {
String name = constPool.getInterfaceMethodrefName(mref);
boolean remove = false;
if ("lock".equals(name)) {
remove = true;
iterator.writeByte(Opcode.MONITORENTER, pos);
} else if ("unlock".equals(name)) {
remove = true;
iterator.writeByte(Opcode.MONITOREXIT, pos);
}
if (remove) {
done++;
iterator.writeByte(Opcode.NOP, pos + 1);
iterator.writeByte(Opcode.NOP, pos + 2);
iterator.writeByte(Opcode.NOP, pos + 3);
iterator.writeByte(Opcode.NOP, pos + 4);
}
}
} else if (op == Opcode.INVOKEVIRTUAL) {
int mref = iterator.u16bitAt(pos + 1);
if (constPool.getMethodrefClassName(mref).endsWith("NativeMutex")) {
String name = constPool.getMethodrefName(mref);
boolean remove = false;
if ("lock".equals(name)) {
remove = true;
iterator.writeByte(Opcode.MONITORENTER, pos);
} else if ("unlock".equals(name)) {
remove = true;
iterator.writeByte(Opcode.MONITOREXIT, pos);
}
if (remove) {
done++;
iterator.writeByte(Opcode.NOP, pos + 1);
iterator.writeByte(Opcode.NOP, pos + 2);
}
}
}
}
methodInfo.rebuildStackMapIf6(ctClass.getClassPool(), ctClass.getClassFile2());