diff --git a/jode/jode/jvm/SyntheticAnalyzer.java.in b/jode/jode/jvm/SyntheticAnalyzer.java.in index 4212806..4e55ef4 100644 --- a/jode/jode/jvm/SyntheticAnalyzer.java.in +++ b/jode/jode/jvm/SyntheticAnalyzer.java.in @@ -43,6 +43,7 @@ public class SyntheticAnalyzer implements Opcodes { public final static int ACCESSGETSTATIC = 5; public final static int ACCESSPUTSTATIC = 6; public final static int ACCESSSTATICMETHOD = 7; + public final static int ACCESSCONSTRUCTOR = 8; int kind = UNKNOWN; Reference reference; @@ -58,6 +59,9 @@ public class SyntheticAnalyzer implements Opcodes { if (!checkName || method.getName().startsWith("access$")) if (checkAccess()) return; + if (method.getName().equals("")) + if (checkConstructorAccess()) + return; } public int getKind() { @@ -151,8 +155,6 @@ public class SyntheticAnalyzer implements Opcodes { if (instr.getOpcode() < opc_ireturn || instr.getOpcode() > opc_areturn) return false; - if (iter.hasNext()) - return false; /* For valid bytecode the type matches automatically */ reference = ref; kind = ACCESSGETSTATIC; @@ -184,8 +186,6 @@ public class SyntheticAnalyzer implements Opcodes { instr = (Instruction) iter.next(); if (instr.getOpcode() != opc_return) return false; - if (iter.hasNext()) - return false; reference = ref; kind = ACCESSPUTSTATIC; return true; @@ -212,8 +212,6 @@ public class SyntheticAnalyzer implements Opcodes { || instr.getOpcode() > opc_areturn) return false; } - if (iter.hasNext()) - return false; /* For valid bytecode the types matches automatically */ reference = ref; @@ -255,8 +253,6 @@ public class SyntheticAnalyzer implements Opcodes { if (instr.getOpcode() < opc_ireturn || instr.getOpcode() > opc_areturn) return false; - if (iter.hasNext()) - return false; /* For valid bytecode the type matches automatically */ reference = ref; kind = ACCESSGETFIELD; @@ -287,8 +283,6 @@ public class SyntheticAnalyzer implements Opcodes { instr = (Instruction) iter.next(); if (instr.getOpcode() != opc_return) return false; - if (iter.hasNext()) - return false; reference = ref; kind = ACCESSPUTFIELD; return true; @@ -314,8 +308,6 @@ public class SyntheticAnalyzer implements Opcodes { || instr.getOpcode() > opc_areturn) return false; } - if (iter.hasNext()) - return false; /* For valid bytecode the types matches automatically */ reference = ref; @@ -324,4 +316,54 @@ public class SyntheticAnalyzer implements Opcodes { } return false; } + + public boolean checkConstructorAccess() { + ClassInfo clazzInfo = method.getClazzInfo(); + BytecodeInfo bytecode = method.getBytecode(); + Handler[] excHandlers = bytecode.getExceptionHandlers(); + if (excHandlers != null && excHandlers.length != 0) + return false; + + Iterator iter = bytecode.getInstructions().iterator(); + Instruction instr = (Instruction) iter.next(); + if (instr.getOpcode() != opc_aload || instr.getLocalSlot() != 0) + return false; + instr = (Instruction) iter.next(); + + // slot begins with 2. Slot 1 contains a dummy value, that + // is used so that the constructor has a different type signature. + int params = 0, slot = 2; + while (instr.getOpcode() >= opc_iload + && instr.getOpcode() <= opc_aload + && instr.getLocalSlot() == slot) { + params++; + slot += (instr.getOpcode() == opc_lload + || instr.getOpcode() == opc_dload) ? 2 : 1; + instr = (Instruction) iter.next(); + } + if (instr.getOpcode() == opc_invokespecial) { + Reference ref = instr.getReference(); + String refClazz = ref.getClazz().substring(1); + if (!(refClazz.substring(0, refClazz.length()-1) + .equals(clazzInfo.getName().replace('.','/')))) + return false; + MethodInfo refMethod + = clazzInfo.findMethod(ref.getName(), ref.getType()); + MethodType refType = Type.tMethod(ref.getType()); + if ((refMethod.getModifiers() & modifierMask) != Modifier.PRIVATE + || !refMethod.getName().equals("") + || refType.getParameterTypes().length != params) + return false; + instr = (Instruction) iter.next(); + if (instr.getOpcode() != opc_return) + return false; + + /* For valid bytecode the types matches automatically */ + reference = ref; + kind = ACCESSCONSTRUCTOR; + return true; + } + return false; + } } +