boolean checkGetClass() { if (!method.isStatic() || !(method.getType().equals("(Ljava/lang/String;)Ljava/lang/Class;"))) return false; BytecodeInfo bytecode = method.getBytecode(); Handler[] excHandlers = bytecode.getExceptionHandlers(); if (excHandlers.length != 1 || !"java.lang.ClassNotFoundException".equals(excHandlers[0].type)) return false; int excSlot = -1; int i = 0; for (Iterator iter = bytecode.getInstructions().iterator(); iter.hasNext(); i++) { Instruction instr = (Instruction) iter.next(); while (instr.getOpcode() == opc_nop && iter.hasNext()) instr = (Instruction) iter.next(); if (i == getClassOpcodes.length || instr.getOpcode() != getClassOpcodes[i]) return false; if (i == 0 && (instr.getLocalSlot() != 0 || excHandlers[0].start != instr)) return false; if (i == 2 && excHandlers[0].end != instr) return false; if (i == 3) { if (excHandlers[0].catcher != instr) return false; excSlot = instr.getLocalSlot(); } if (i == 4 && !instr.getClazzType().equals("Ljava/lang/NoClassDefFoundError;")) return false; if (i == 6 && instr.getLocalSlot() != excSlot) return false; if (getClassRefs[i] != null && !getClassRefs[i].equals(instr.getReference())) return false; } this.kind = GETCLASS; return true; }
public boolean checkConstructorAccess() { ClassInfo clazzInfo = method.getClazzInfo(); BytecodeInfo bytecode = method.getBytecode(); String[] paramTypes = TypeSignature.getParameterTypes(method.getType()); Handler[] excHandlers = bytecode.getExceptionHandlers(); if (excHandlers != null && excHandlers.length != 0) return false; Iterator iter = bytecode.getInstructions().iterator(); Instruction instr = (Instruction) iter.next(); while (instr.getOpcode() == opc_nop && iter.hasNext()) instr = (Instruction) iter.next(); int params = 0, slot = 0; while (instr.getOpcode() >= opc_iload && instr.getOpcode() <= opc_aload) { if (instr.getLocalSlot() > slot && unifyParam == -1 && params > 0 && paramTypes[params - 1].charAt(0) == 'L') { unifyParam = params; params++; slot++; } if (instr.getLocalSlot() != slot) return false; params++; slot += (instr.getOpcode() == opc_lload || instr.getOpcode() == opc_dload) ? 2 : 1; instr = (Instruction) iter.next(); } if (params > 0 && instr.getOpcode() == opc_invokespecial) { if (unifyParam == -1 && params <= paramTypes.length && paramTypes[params - 1].charAt(0) == 'L') unifyParam = params++; Reference ref = instr.getReference(); ClassInfo refClazz = TypeSignature.getClassInfo(ref.getClazz()); if (refClazz != clazzInfo) return false; MethodInfo refMethod = refClazz.findMethod(ref.getName(), ref.getType()); MethodType refType = Type.tMethod(ref.getType()); if ((refMethod.getModifiers() & modifierMask) != 0 || !refMethod.getName().equals("<init>") || unifyParam == -1 || refType.getParameterTypes().length != params - 2) return false; instr = (Instruction) iter.next(); if (instr.getOpcode() != opc_return) return false; /* * We don't check if types matches. No problem since we only need to * make sure, this constructor doesn't do anything more than relay * to the real one. */ reference = ref; kind = ACCESSCONSTRUCTOR; return true; } return false; }