То, что у вас есть, является почти правильным, но не учитывает другие типы кодов операций, вызываемых после ldc, так что вы вызовете некоторую поломку, так как они будут искать что-то в стеке, чтоне там (так как вы не посетили ldc).Я не уверен в удалении существующей константы, но вы можете заменить константу следующим образом:
@Override
public void visitInsn(int opcode) {
if (opcode == IMUL && replace) {
operand *= 2;
mv.visitInsn(POP);
mv.visitLdcInsn(operand);
replace = false;
}
mv.visitInsn(opcode);
}
@Override
public void visitLdcInsn(Object cst) {
if (cst instanceof Integer && !replace) {
operand = (Integer) cst;
replace = true;
}
mv.visitLdcInsn(cst);
}
Другими словами, всегда посещайте "ldc".Если затем вы видите, как IMUL обрабатывает его, вытолкните стек, вставьте новую константу и затем посетите код операции IMUL.Вам нужно будет немного поработать, чтобы сделать это полностью безопасным, если какой-то другой метод будет посещен после посещения ldc и до IMUL.Чтобы быть параноиком, вы можете переопределить все методы посетителя, и если это не визитИнсн или не IMUL, вы должны посетить ldc и установить replace = false.
Полностью заменить константу немного сложнее.Вам нужно будет вспомнить, какие константы были видны всеми методами, посещенными в классе до сих пор.Если вы еще не видели эту константу, вы можете просто заменить значение при посещении ldc.