/** * Gets the method bridged to by a {@linkplain ResolvedJavaMethod#isBridge() bridge} method. The * value returned is the method called by {@code method} that has the same name as {@code bridge}. * * @param bridge a bridge method * @return the method called by {@code bridge} whose name is the same as {@code bridge.getName()} */ public static ResolvedJavaMethod getBridgedMethod(ResolvedJavaMethod bridge) { assert bridge.isBridge(); Bytecode code = new ResolvedJavaMethodBytecode(bridge); BytecodeStream stream = new BytecodeStream(code.getCode()); int opcode = stream.currentBC(); ResolvedJavaMethod bridged = null; while (opcode != Bytecodes.END) { switch (opcode) { case INVOKEVIRTUAL: case INVOKESPECIAL: case INVOKESTATIC: case INVOKEINTERFACE: { int cpi = stream.readCPI(); ConstantPool cp = code.getConstantPool(); cp.loadReferencedType(cpi, opcode); ResolvedJavaMethod method = (ResolvedJavaMethod) cp.lookupMethod(cpi, opcode); if (method.getName().equals(bridge.getName())) { if (!assertionsEnabled()) { return method; } assert bridged == null || bridged.equals(method) : String.format( "Found calls to different methods named %s in bridge method %s%n callee 1: %s%n callee 2: %s", bridge.getName(), bridge.format("%R %H.%n(%P)"), bridged.format("%R %H.%n(%P)"), method.format("%R %H.%n(%P)")); bridged = method; } break; } } stream.next(); opcode = stream.currentBC(); } if (bridged == null) { throw new InternalError("Couldn't find method bridged by " + bridge.format("%R %H.%n(%P)")); } return bridged; }
public static BytecodeBipush at(BytecodeStream bcs) { return new BytecodeBipush(bcs.method(), bcs.bci()); }
public static BytecodeFastAAccess0 at(BytecodeStream bcs) { return new BytecodeFastAAccess0(bcs.method(), bcs.bci()); }
public static BytecodeGetField at(BytecodeStream bcs) { return new BytecodeGetField(bcs.method(), bcs.bci()); }