下面列出了怎么用org.objectweb.asm.tree.InvokeDynamicInsnNode的API类实例代码及写法,或者点击链接到github查看源代码。
private void createCallWeavers() {
MethodFlow mf = methodFlow;
for (BasicBlock bb : mf.getBasicBlocks()) {
//if (!bb.isPausable() || bb.startFrame==null) continue;
if (!bb.isMethodCall() || bb.startFrame==null) continue;
if(bb.getInstruction(bb.startPos) instanceof InvokeDynamicInsnNode) {
continue;
}
//if (!(bb.getInstruction(bb.startPos) instanceof MethodInsnNode) || bb.startFrame==null) continue;
// No prelude needed for Task.getCurrentTask().
if (bb.isGetCurrentTask()) continue;
MethodInvokationWeaver cw = new MethodInvokationWeaver(this, bb);
callWeavers.add(cw);
}
}
private void invokeDynamicOnLambda(MethodVisitor mv, AbstractInsnNode ain) {
InvokeDynamicInsnNode indy = (InvokeDynamicInsnNode)ain;
Object[]bsmArgs = indy.bsmArgs;
// Is it a lambda conversion
if (indy.bsm.getOwner().equals("java/lang/invoke/LambdaMetafactory")) {
Handle lambdaBody = (Handle)bsmArgs[1];
Detector detector = this.methodFlow.detector();
String desc = lambdaBody.getDesc();
//if (detector.isPausable(lambdaBody.getOwner(), lambdaBody.getName(), desc)) {
//if(!lambdaBody.getName().equals("<init>")) {
bsmArgs[0] = addFiberType((org.objectweb.asm.Type)bsmArgs[0]);
bsmArgs[1] = new Handle(lambdaBody.getTag(),
lambdaBody.getOwner(),
lambdaBody.getName(),
desc.replace(")", D_FIBER + ")"));
bsmArgs[2] = addFiberType((org.objectweb.asm.Type)bsmArgs[2]);
//}
//}
}
ain.accept(mv);
}
public InsnValue onMethod(AbstractInsnNode insn, List<InsnValue> values) {
String desc = "V";
if (insn.getOpcode() == Opcodes.INVOKEDYNAMIC){
desc = ((InvokeDynamicInsnNode) insn).desc;
}else{
desc = ((MethodInsnNode) insn).desc;
}
// Until I'm ready to simulate method calls the opcode here really
// doesn't matter.
/*
* switch (insn.getOpcode()) { case Opcodes.INVOKEDYNAMIC: case
* Opcodes.INVOKESPECIAL: case Opcodes.INVOKEINTERFACE: case
* Opcodes.INVOKESTATIC: case Opcodes.INVOKEVIRTUAL: }
*/
if (desc.endsWith("V")) {
return null;
}
return new InsnValue(Type.getReturnType(desc));
}
private void visitInvokeDynamic(InvokeDynamicInsnNode idin) {
InvokeDynamicExpression idye = new InvokeDynamicExpression(idin.name, idin.desc, idin.bsmArgs, idin.bsm);
Handle methodHandle = idye.getMethodHandle();
if (methodHandle != null) {
ArrayList<Integer> descSizes = DescUtils.getInnerDescSizes(methodHandle.getDesc());
List<Expression> args = new ArrayList<>();
for (int i : descSizes) {
if (i == 1) {
args.add(stack.pop());
} else {
args.add(stack.pop2());
}
}
Collections.reverse(args);
idye.setArgs(args);
}
stack.push(idye);
}
private int findInvokeDynamic() {
AtomicInteger total = new AtomicInteger();
classNodes().forEach(classNode -> {
classNode.methods.forEach(methodNode -> {
for (int i = 0; i < methodNode.instructions.size(); i++) {
AbstractInsnNode abstractInsnNode = methodNode.instructions.get(i);
if (abstractInsnNode instanceof InvokeDynamicInsnNode) {
InvokeDynamicInsnNode dyn = (InvokeDynamicInsnNode) abstractInsnNode;
if (dyn.bsmArgs.length > 0 && dyn.bsmArgs[0] instanceof String) {
total.incrementAndGet();
}
}
}
});
});
return total.get();
}
protected Object[] findOwnerInvokeDynamic(AbstractInsnNode instruction, List<MethodNode> ownerMethods) {
if (instruction instanceof InvokeDynamicInsnNode) {
InvokeDynamicInsnNode n = (InvokeDynamicInsnNode) instruction;
Handle bsm = n.bsm;
if ("java/lang/invoke/LambdaMetafactory".equals(bsm.getOwner()) && "metafactory".equals(bsm.getName())) {
Handle method = Arrays
.stream(n.bsmArgs)
.filter(Handle.class::isInstance)
.map(Handle.class::cast)
.filter(h -> h.getOwner().equals(classNode.name) /*&& h.getName().startsWith("lambda$")*/)
.findFirst()
.orElse(null);
if (null != method) {
MethodNode targetMethodNode = getMethod(method.getName(), method.getDesc(), ownerMethods);
if (null != targetMethodNode && (targetMethodNode.access & (/*ACC_STATIC + ACC_PRIVATE +*/ ACC_SYNTHETIC)) == /*ACC_STATIC + ACC_PRIVATE + */ACC_SYNTHETIC) {
return new Object[] {method, targetMethodNode};
}
}
}
}
return null;
}
@Override
public BasicValue naryOperation(final AbstractInsnNode insn, final List<? extends BasicValue> values)
throws AnalyzerException {
int opcode = insn.getOpcode();
if (opcode == MULTIANEWARRAY) {
return newValue(Type.getType(((MultiANewArrayInsnNode) insn).desc));
} else if (opcode == INVOKEDYNAMIC) {
return newValue(Type.getReturnType(((InvokeDynamicInsnNode) insn).desc));
} else {
return newValue(Type.getReturnType(((MethodInsnNode) insn).desc));
}
}
@Override
public SourceValue naryOperation(final AbstractInsnNode insn, final List<? extends SourceValue> values) {
int size;
int opcode = insn.getOpcode();
if (opcode == MULTIANEWARRAY) {
size = 1;
} else if (opcode == INVOKEDYNAMIC) {
size = Type.getReturnType(((InvokeDynamicInsnNode) insn).desc).getSize();
} else {
size = Type.getReturnType(((MethodInsnNode) insn).desc).getSize();
}
return new SourceValue(size, insn);
}
@Override
public BasicValue naryOperation(final AbstractInsnNode insn, final List<? extends BasicValue> values)
throws AnalyzerException {
int opcode = insn.getOpcode();
if (opcode == MULTIANEWARRAY) {
for (BasicValue value : values) {
if (!BasicValue.INT_VALUE.equals(value)) {
throw new AnalyzerException(insn, null, BasicValue.INT_VALUE, value);
}
}
} else {
int i = 0;
int j = 0;
if (opcode != INVOKESTATIC && opcode != INVOKEDYNAMIC) {
Type owner = Type.getObjectType(((MethodInsnNode) insn).owner);
if (!isSubTypeOf(values.get(i++), newValue(owner))) {
throw new AnalyzerException(insn, "Method owner", newValue(owner), values.get(0));
}
}
String methodDescriptor = (opcode == INVOKEDYNAMIC) ? ((InvokeDynamicInsnNode) insn).desc
: ((MethodInsnNode) insn).desc;
Type[] args = Type.getArgumentTypes(methodDescriptor);
while (i < values.size()) {
BasicValue expected = newValue(args[j++]);
BasicValue actual = values.get(i++);
if (!isSubTypeOf(actual, expected)) {
throw new AnalyzerException(insn, "Argument " + j, expected, actual);
}
}
}
return super.naryOperation(insn, values);
}
@Override
public CoffeeValue naryOperation(final AbstractInsnNode insn, final List<? extends CoffeeValue> values)
throws AnalyzerException {
int opcode = insn.getOpcode();
if (opcode == MULTIANEWARRAY) {
return newValue(Type.getType(((MultiANewArrayInsnNode) insn).desc));
} else if (opcode == INVOKEDYNAMIC) {
return newValue(Type.getReturnType(((InvokeDynamicInsnNode) insn).desc));
} else {
return newValue(Type.getReturnType(((MethodInsnNode) insn).desc));
}
}
private void processIndy(ClassNode classNode, String methodName, InvokeDynamicInsnNode indy) {
MethodNode indyWrapper = new MethodNode(Opcodes.ASM7,
Opcodes.ACC_PRIVATE | Opcodes.ACC_FINAL | Opcodes.ACC_SYNTHETIC | Opcodes.ACC_STATIC, methodName,
indy.desc, null, new String[0]);
int localVarsPosition = 0;
for (Type arg : Type.getArgumentTypes(indy.desc)) {
indyWrapper.instructions.add(new VarInsnNode(arg.getOpcode(Opcodes.ILOAD), localVarsPosition));
localVarsPosition += arg.getSize();
}
indyWrapper.instructions.add(new InvokeDynamicInsnNode(indy.name, indy.desc, indy.bsm, indy.bsmArgs));
indyWrapper.instructions.add(new InsnNode(Opcodes.ARETURN));
classNode.methods.add(indyWrapper);
}
@Override
public BasicValue naryOperation(
final AbstractInsnNode insn, final List<? extends BasicValue> values)
throws AnalyzerException {
int opcode = insn.getOpcode();
if (opcode == MULTIANEWARRAY) {
return newValue(Type.getType(((MultiANewArrayInsnNode) insn).desc));
} else if (opcode == INVOKEDYNAMIC) {
return newValue(Type.getReturnType(((InvokeDynamicInsnNode) insn).desc));
} else {
return newValue(Type.getReturnType(((MethodInsnNode) insn).desc));
}
}
@Override
public SourceValue naryOperation(
final AbstractInsnNode insn, final List<? extends SourceValue> values) {
int size;
int opcode = insn.getOpcode();
if (opcode == MULTIANEWARRAY) {
size = 1;
} else if (opcode == INVOKEDYNAMIC) {
size = Type.getReturnType(((InvokeDynamicInsnNode) insn).desc).getSize();
} else {
size = Type.getReturnType(((MethodInsnNode) insn).desc).getSize();
}
return new SourceValue(size, insn);
}
@Override
public BasicValue naryOperation(
final AbstractInsnNode insn, final List<? extends BasicValue> values)
throws AnalyzerException {
int opcode = insn.getOpcode();
if (opcode == MULTIANEWARRAY) {
for (BasicValue value : values) {
if (!BasicValue.INT_VALUE.equals(value)) {
throw new AnalyzerException(insn, null, BasicValue.INT_VALUE, value);
}
}
} else {
int i = 0;
int j = 0;
if (opcode != INVOKESTATIC && opcode != INVOKEDYNAMIC) {
Type owner = Type.getObjectType(((MethodInsnNode) insn).owner);
if (!isSubTypeOf(values.get(i++), newValue(owner))) {
throw new AnalyzerException(insn, "Method owner", newValue(owner), values.get(0));
}
}
String methodDescriptor =
(opcode == INVOKEDYNAMIC)
? ((InvokeDynamicInsnNode) insn).desc
: ((MethodInsnNode) insn).desc;
Type[] args = Type.getArgumentTypes(methodDescriptor);
while (i < values.size()) {
BasicValue expected = newValue(args[j++]);
BasicValue actual = values.get(i++);
if (!isSubTypeOf(actual, expected)) {
throw new AnalyzerException(insn, "Argument " + j, expected, actual);
}
}
}
return super.naryOperation(insn, values);
}
private void removeUnwantedCalls(InsnList decryption) {
// TODO remove unwanted methodinsnnodes
for (AbstractInsnNode ain : decryption.toArray()) {
if (ain.getOpcode() == INVOKEDYNAMIC) {
InvokeDynamicInsnNode idin = (InvokeDynamicInsnNode) ain;
if (idin.desc.equals("(IJ)Ljava/lang/String;")) {
decryption.insertBefore(idin, new InsnNode(POP2));
decryption.insert(idin, new LdcInsnNode("<clinit> decryption invokedynamic string undecrypted"));
decryption.set(idin, new InsnNode(POP));
}
}
}
}
@Override
public BasicValue naryOperation(final AbstractInsnNode insn, final List<? extends BasicValue> values) throws AnalyzerException {
int opcode = insn.getOpcode();
if (opcode == MULTIANEWARRAY) {
return newValue(Type.getType(((MultiANewArrayInsnNode) insn).desc));
} else if (opcode == INVOKEDYNAMIC) {
return newValue(Type.getReturnType(((InvokeDynamicInsnNode) insn).desc));
} else {
return newValue(Type.getReturnType(((MethodInsnNode) insn).desc));
}
}
@Override
public SourceValue naryOperation(final AbstractInsnNode insn, final List<? extends SourceValue> values) {
int size;
int opcode = insn.getOpcode();
if (opcode == MULTIANEWARRAY) {
size = 1;
} else {
String desc = (opcode == INVOKEDYNAMIC) ? ((InvokeDynamicInsnNode) insn).desc : ((MethodInsnNode) insn).desc;
size = Type.getReturnType(desc).getSize();
}
return new SourceValue(size, insn);
}
@Override
public ConstValue naryOperation(AbstractInsnNode insn, List<? extends ConstValue> values) {
int opcode = insn.getOpcode();
if (opcode == MULTIANEWARRAY) {
return ConstValue.ONE_SLOT;
}
var desc = (opcode == INVOKEDYNAMIC) ? ((InvokeDynamicInsnNode) insn).desc
: ((MethodInsnNode) insn).desc;
return ConstValue.slotForSize(Type.getReturnType(desc).getSize());
}
@Override
public BasicValue naryOperation(
final AbstractInsnNode insn, final List<? extends BasicValue> values)
throws AnalyzerException {
int opcode = insn.getOpcode();
if (opcode == MULTIANEWARRAY) {
return newValue(Type.getType(((MultiANewArrayInsnNode) insn).desc));
} else if (opcode == INVOKEDYNAMIC) {
return newValue(Type.getReturnType(((InvokeDynamicInsnNode) insn).desc));
} else {
return newValue(Type.getReturnType(((MethodInsnNode) insn).desc));
}
}
@Override
public SourceValue naryOperation(
final AbstractInsnNode insn, final List<? extends SourceValue> values) {
int size;
int opcode = insn.getOpcode();
if (opcode == MULTIANEWARRAY) {
size = 1;
} else if (opcode == INVOKEDYNAMIC) {
size = Type.getReturnType(((InvokeDynamicInsnNode) insn).desc).getSize();
} else {
size = Type.getReturnType(((MethodInsnNode) insn).desc).getSize();
}
return new SourceValue(size, insn);
}
@Override
public BasicValue naryOperation(
final AbstractInsnNode insn, final List<? extends BasicValue> values)
throws AnalyzerException {
int opcode = insn.getOpcode();
if (opcode == MULTIANEWARRAY) {
for (BasicValue value : values) {
if (!BasicValue.INT_VALUE.equals(value)) {
throw new AnalyzerException(insn, null, BasicValue.INT_VALUE, value);
}
}
} else {
int i = 0;
int j = 0;
if (opcode != INVOKESTATIC && opcode != INVOKEDYNAMIC) {
Type owner = Type.getObjectType(((MethodInsnNode) insn).owner);
if (!isSubTypeOf(values.get(i++), newValue(owner))) {
throw new AnalyzerException(insn, "Method owner", newValue(owner), values.get(0));
}
}
String methodDescriptor =
(opcode == INVOKEDYNAMIC)
? ((InvokeDynamicInsnNode) insn).desc
: ((MethodInsnNode) insn).desc;
Type[] args = Type.getArgumentTypes(methodDescriptor);
while (i < values.size()) {
BasicValue expected = newValue(args[j++]);
BasicValue actual = values.get(i++);
if (!isSubTypeOf(actual, expected)) {
throw new AnalyzerException(insn, "Argument " + j, expected, actual);
}
}
}
return super.naryOperation(insn, values);
}
@Override
public BasicValue naryOperation(
final AbstractInsnNode insn, final List<? extends BasicValue> values)
throws AnalyzerException {
int opcode = insn.getOpcode();
if (opcode == MULTIANEWARRAY) {
return newValue(Type.getType(((MultiANewArrayInsnNode) insn).desc));
} else if (opcode == INVOKEDYNAMIC) {
return newValue(Type.getReturnType(((InvokeDynamicInsnNode) insn).desc));
} else {
return newValue(Type.getReturnType(((MethodInsnNode) insn).desc));
}
}
@Override
public SourceValue naryOperation(
final AbstractInsnNode insn, final List<? extends SourceValue> values) {
int size;
int opcode = insn.getOpcode();
if (opcode == MULTIANEWARRAY) {
size = 1;
} else if (opcode == INVOKEDYNAMIC) {
size = Type.getReturnType(((InvokeDynamicInsnNode) insn).desc).getSize();
} else {
size = Type.getReturnType(((MethodInsnNode) insn).desc).getSize();
}
return new SourceValue(size, insn);
}
@Override
public BasicValue naryOperation(
final AbstractInsnNode insn, final List<? extends BasicValue> values)
throws AnalyzerException {
int opcode = insn.getOpcode();
if (opcode == MULTIANEWARRAY) {
for (BasicValue value : values) {
if (!BasicValue.INT_VALUE.equals(value)) {
throw new AnalyzerException(insn, null, BasicValue.INT_VALUE, value);
}
}
} else {
int i = 0;
int j = 0;
if (opcode != INVOKESTATIC && opcode != INVOKEDYNAMIC) {
Type owner = Type.getObjectType(((MethodInsnNode) insn).owner);
if (!isSubTypeOf(values.get(i++), newValue(owner))) {
throw new AnalyzerException(insn, "Method owner", newValue(owner), values.get(0));
}
}
String methodDescriptor =
(opcode == INVOKEDYNAMIC)
? ((InvokeDynamicInsnNode) insn).desc
: ((MethodInsnNode) insn).desc;
Type[] args = Type.getArgumentTypes(methodDescriptor);
while (i < values.size()) {
BasicValue expected = newValue(args[j++]);
BasicValue actual = values.get(i++);
if (!isSubTypeOf(actual, expected)) {
throw new AnalyzerException(insn, "Argument " + j, expected, actual);
}
}
}
return super.naryOperation(insn, values);
}
/**
* Clones an invokevirtual/invokespecial/invokeinterface/invokedynamic node and returns it as an instruction list.
* @param insnNode instruction to clone
* @throws NullPointerException if any argument is {@code null}
* @throws IllegalArgumentException if node isn't of invoke type
* @return instruction list with cloned instruction
*/
public static InsnList cloneInvokeNode(AbstractInsnNode insnNode) {
Validate.notNull(insnNode);
Validate.isTrue(insnNode instanceof MethodInsnNode || insnNode instanceof InvokeDynamicInsnNode);
InsnList ret = new InsnList();
ret.add(insnNode.clone(new HashMap<>()));
return ret;
}
@Override
public void visitInvokeDynamicInsn(String name, String desc, Handle bsm, Object... bsmArgs) {
InvokeDynamicInsnNode mnode = new InvokeDynamicInsnNode(name, desc, bsm, bsmArgs);
if (needsFrameGuard(INVOKEDYNAMIC, bsm.getOwner(), name, desc)) {
Label label = new Label();
super.visitLabel(label);
labels.add(label);
nodes.add(mnode);
}
instructions.add(mnode);
}
private int findCallSiteInvocationInsertionIndex(MethodInsnNode mnode) {
int inSelected = -1;
for (AbstractInsnNode otherIns = mnode; otherIns != null && inSelected < 0; ) {
otherIns = otherIns.getNext();
if (otherIns instanceof MethodInsnNode || otherIns instanceof InvokeDynamicInsnNode) {
inSelected = nodes.indexOf(otherIns);
}
}
return inSelected;
}
@Override
public void visitInvokeDynamicInsn(String name, String desc, Handle bsm, Object... bsmArgs) {
InvokeDynamicInsnNode mnode = new InvokeDynamicInsnNode(name, desc, bsm, bsmArgs);
if (needsFrameGuard(INVOKEDYNAMIC, bsm.getOwner(), name, desc)) {
Label label = new Label();
super.visitLabel(label);
labels.add(label);
nodes.add(mnode);
}
instructions.add(mnode);
}
@Override
public void visitInvokeDynamicInsn(String name, String descriptor, Handle bootstrapMethodHandle, Object... bootstrapMethodArguments) {
// Create a shallow copy of the bootstrap method args because the
// base implementation just passes the array by reference. This
// causes any changes applied to the cloned classnode to leak into
// the "master" ClassNode!
Object[] bsmArgs = new Object[bootstrapMethodArguments.length];
System.arraycopy(bootstrapMethodArguments, 0, bsmArgs, 0, bootstrapMethodArguments.length);
this.instructions.add(new InvokeDynamicInsnNode(name, descriptor, bootstrapMethodHandle, bsmArgs));
}
public CodeBlock invokedynamic(final String name, final String descriptor,
final Handle bootstrapMethod, final Object... bootstrapArguments)
{
instructionList.add(new InvokeDynamicInsnNode(name, descriptor,
bootstrapMethod, bootstrapArguments));
return this;
}