mirror of
https://gitee.com/arthas/arthas.git
synced 2024-12-04 05:09:54 +08:00
better invoke location support, support invoke method name/desc/owner
This commit is contained in:
parent
4a936476cc
commit
3d3640e80e
@ -185,18 +185,51 @@ public abstract class Binding {
|
||||
@java.lang.annotation.Target(ElementType.PARAMETER)
|
||||
@BindingParserHandler(parser = InvokeReturnBindingParser.class)
|
||||
public static @interface InvokeReturn {
|
||||
|
||||
|
||||
boolean optional() default false;
|
||||
|
||||
}
|
||||
|
||||
|
||||
public static class InvokeReturnBindingParser implements BindingParser {
|
||||
@Override
|
||||
public Binding parse(Annotation annotation) {
|
||||
return new InvokeReturnBinding();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@Documented
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@java.lang.annotation.Target(ElementType.PARAMETER)
|
||||
@BindingParserHandler(parser = InvokeMethodNameBindingParser.class)
|
||||
public static @interface InvokeMethodName {
|
||||
|
||||
boolean optional() default false;
|
||||
|
||||
}
|
||||
|
||||
public static class InvokeMethodNameBindingParser implements BindingParser {
|
||||
@Override
|
||||
public Binding parse(Annotation annotation) {
|
||||
return new InvokeMethodNameBinding();
|
||||
}
|
||||
}
|
||||
|
||||
@Documented
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
@java.lang.annotation.Target(ElementType.PARAMETER)
|
||||
@BindingParserHandler(parser = InvokeMethodOwnerBindingParser.class)
|
||||
public static @interface InvokeMethodOwner {
|
||||
|
||||
boolean optional() default false;
|
||||
|
||||
}
|
||||
|
||||
public static class InvokeMethodOwnerBindingParser implements BindingParser {
|
||||
@Override
|
||||
public Binding parse(Annotation annotation) {
|
||||
return new InvokeMethodOwnerBinding();
|
||||
}
|
||||
}
|
||||
|
||||
@Documented
|
||||
@Retention(RetentionPolicy.RUNTIME)
|
||||
|
@ -1,12 +1,11 @@
|
||||
package com.taobao.arthas.bytekit.asm.binding;
|
||||
|
||||
import com.alibaba.arthas.deps.org.objectweb.asm.Type;
|
||||
import com.alibaba.arthas.deps.org.objectweb.asm.tree.AbstractInsnNode;
|
||||
import com.alibaba.arthas.deps.org.objectweb.asm.tree.InsnList;
|
||||
import com.alibaba.arthas.deps.org.objectweb.asm.tree.MethodInsnNode;
|
||||
|
||||
import com.taobao.arthas.bytekit.asm.location.MethodInsnNodeWare;
|
||||
import com.taobao.arthas.bytekit.asm.location.Location;
|
||||
import com.taobao.arthas.bytekit.utils.AsmOpUtils;
|
||||
import com.taobao.arthas.bytekit.utils.AsmUtils;
|
||||
|
||||
/**
|
||||
*
|
||||
@ -17,15 +16,15 @@ public class InvokeMethodDeclarationBinding extends Binding {
|
||||
|
||||
@Override
|
||||
public void pushOntoStack(InsnList instructions, BindingContext bindingContext) {
|
||||
AbstractInsnNode insnNode = bindingContext.getLocation().getInsnNode();
|
||||
if (insnNode instanceof MethodInsnNode) {
|
||||
MethodInsnNode methodInsnNode = (MethodInsnNode) insnNode;
|
||||
String methodDeclaration = AsmUtils.methodDeclaration(methodInsnNode);
|
||||
AsmOpUtils.push(instructions, methodDeclaration);
|
||||
Location location = bindingContext.getLocation();
|
||||
if (location instanceof MethodInsnNodeWare) {
|
||||
MethodInsnNodeWare methodInsnNodeWare = (MethodInsnNodeWare) location;
|
||||
MethodInsnNode methodInsnNode = methodInsnNodeWare.methodInsnNode();
|
||||
AsmOpUtils.push(instructions, methodInsnNode.desc);
|
||||
|
||||
} else {
|
||||
throw new IllegalArgumentException(
|
||||
"InvokeMethodDeclarationBinding location is not MethodInsnNode, insnNode: " + insnNode);
|
||||
"InvokeMethodDeclarationBinding location is not Invocation location, location: " + location);
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -0,0 +1,37 @@
|
||||
package com.taobao.arthas.bytekit.asm.binding;
|
||||
|
||||
import com.alibaba.arthas.deps.org.objectweb.asm.Type;
|
||||
import com.alibaba.arthas.deps.org.objectweb.asm.tree.InsnList;
|
||||
import com.alibaba.arthas.deps.org.objectweb.asm.tree.MethodInsnNode;
|
||||
import com.taobao.arthas.bytekit.asm.location.MethodInsnNodeWare;
|
||||
import com.taobao.arthas.bytekit.asm.location.Location;
|
||||
import com.taobao.arthas.bytekit.utils.AsmOpUtils;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author hengyunabc
|
||||
*
|
||||
*/
|
||||
public class InvokeMethodNameBinding extends Binding {
|
||||
|
||||
@Override
|
||||
public void pushOntoStack(InsnList instructions, BindingContext bindingContext) {
|
||||
Location location = bindingContext.getLocation();
|
||||
if (location instanceof MethodInsnNodeWare) {
|
||||
MethodInsnNodeWare methodInsnNodeWare = (MethodInsnNodeWare) location;
|
||||
MethodInsnNode methodInsnNode = methodInsnNodeWare.methodInsnNode();
|
||||
AsmOpUtils.push(instructions, methodInsnNode.name);
|
||||
|
||||
} else {
|
||||
throw new IllegalArgumentException(
|
||||
"InvokeMethodNameBinding location is not Invocation location, location: " + location);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public Type getType(BindingContext bindingContext) {
|
||||
return Type.getType(String.class);
|
||||
}
|
||||
|
||||
}
|
@ -0,0 +1,37 @@
|
||||
package com.taobao.arthas.bytekit.asm.binding;
|
||||
|
||||
import com.alibaba.arthas.deps.org.objectweb.asm.Type;
|
||||
import com.alibaba.arthas.deps.org.objectweb.asm.tree.InsnList;
|
||||
import com.alibaba.arthas.deps.org.objectweb.asm.tree.MethodInsnNode;
|
||||
import com.taobao.arthas.bytekit.asm.location.MethodInsnNodeWare;
|
||||
import com.taobao.arthas.bytekit.asm.location.Location;
|
||||
import com.taobao.arthas.bytekit.utils.AsmOpUtils;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author hengyunabc 2020-05-02
|
||||
*
|
||||
*/
|
||||
public class InvokeMethodOwnerBinding extends Binding {
|
||||
|
||||
@Override
|
||||
public void pushOntoStack(InsnList instructions, BindingContext bindingContext) {
|
||||
Location location = bindingContext.getLocation();
|
||||
if (location instanceof MethodInsnNodeWare) {
|
||||
MethodInsnNodeWare methodInsnNodeWare = (MethodInsnNodeWare) location;
|
||||
MethodInsnNode methodInsnNode = methodInsnNodeWare.methodInsnNode();
|
||||
AsmOpUtils.push(instructions, methodInsnNode.owner);
|
||||
|
||||
} else {
|
||||
throw new IllegalArgumentException(
|
||||
"InvokeMethodOwnerBinding location is not Invocation location, location: " + location);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public Type getType(BindingContext bindingContext) {
|
||||
return Type.getType(String.class);
|
||||
}
|
||||
|
||||
}
|
@ -1,17 +1,28 @@
|
||||
package com.taobao.arthas.bytekit.asm.location;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import com.alibaba.arthas.deps.org.objectweb.asm.Opcodes;
|
||||
import com.alibaba.arthas.deps.org.objectweb.asm.Type;
|
||||
import com.alibaba.arthas.deps.org.objectweb.asm.tree.AbstractInsnNode;
|
||||
import com.alibaba.arthas.deps.org.objectweb.asm.tree.InsnList;
|
||||
import com.alibaba.arthas.deps.org.objectweb.asm.tree.JumpInsnNode;
|
||||
import com.alibaba.arthas.deps.org.objectweb.asm.tree.LabelNode;
|
||||
import com.alibaba.arthas.deps.org.objectweb.asm.tree.MethodInsnNode;
|
||||
|
||||
import com.alibaba.arthas.deps.org.objectweb.asm.tree.MethodNode;
|
||||
import com.taobao.arthas.bytekit.asm.MethodProcessor;
|
||||
import com.taobao.arthas.bytekit.asm.TryCatchBlock;
|
||||
import com.taobao.arthas.bytekit.asm.location.Location.InvokeExceptionExitLocation;
|
||||
import com.taobao.arthas.bytekit.asm.location.Location.InvokeLocation;
|
||||
import com.taobao.arthas.bytekit.utils.AsmOpUtils;
|
||||
import com.taobao.arthas.bytekit.utils.MatchUtils;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author hengyunabc
|
||||
*
|
||||
*/
|
||||
public class InvokeLocationMatcher implements LocationMatcher {
|
||||
|
||||
/**
|
||||
@ -21,8 +32,7 @@ public class InvokeLocationMatcher implements LocationMatcher {
|
||||
private String methodName;
|
||||
|
||||
/**
|
||||
* the name of the type to which the method belongs or null if any type will
|
||||
* do
|
||||
* the name of the type to which the method belongs or null if any type will do
|
||||
*/
|
||||
private String owner;
|
||||
|
||||
@ -32,8 +42,8 @@ public class InvokeLocationMatcher implements LocationMatcher {
|
||||
private String desc;
|
||||
|
||||
/**
|
||||
* count identifying which invocation should be taken as the trigger point.
|
||||
* if not specified as a parameter this defaults to the first invocation.
|
||||
* count identifying which invocation should be taken as the trigger point. if
|
||||
* not specified as a parameter this defaults to the first invocation.
|
||||
*/
|
||||
private int count;
|
||||
|
||||
@ -44,12 +54,15 @@ public class InvokeLocationMatcher implements LocationMatcher {
|
||||
private boolean whenComplete;
|
||||
|
||||
/**
|
||||
* wildcard matcher to exclude class, such as java.* to exclude jdk invoke.
|
||||
* wildcard matcher to exclude the invoke class, such as java.* to exclude jdk
|
||||
* invoke.
|
||||
*/
|
||||
private List<String> excludes = new ArrayList<String>();
|
||||
|
||||
|
||||
private boolean atInvokeExcpetionExit = false;
|
||||
|
||||
public InvokeLocationMatcher(String owner, String methodName, String desc, int count, boolean whenComplete,
|
||||
List<String> excludes) {
|
||||
List<String> excludes, boolean atInvokeExcpetionExit) {
|
||||
super();
|
||||
this.owner = owner;
|
||||
this.methodName = methodName;
|
||||
@ -57,6 +70,12 @@ public class InvokeLocationMatcher implements LocationMatcher {
|
||||
this.count = count;
|
||||
this.whenComplete = whenComplete;
|
||||
this.excludes = excludes;
|
||||
this.atInvokeExcpetionExit = atInvokeExcpetionExit;
|
||||
}
|
||||
|
||||
public InvokeLocationMatcher(String owner, String methodName, String desc, int count, boolean whenComplete,
|
||||
List<String> excludes) {
|
||||
this(owner, methodName, desc, count, whenComplete, excludes, false);
|
||||
}
|
||||
|
||||
public InvokeLocationMatcher(String owner, String methodName, String desc, int count, boolean whenComplete) {
|
||||
@ -65,9 +84,12 @@ public class InvokeLocationMatcher implements LocationMatcher {
|
||||
|
||||
@Override
|
||||
public List<Location> match(MethodProcessor methodProcessor) {
|
||||
if (this.atInvokeExcpetionExit) {
|
||||
return matchForException(methodProcessor);
|
||||
}
|
||||
List<Location> locations = new ArrayList<Location>();
|
||||
AbstractInsnNode insnNode = methodProcessor.getEnterInsnNode();
|
||||
|
||||
|
||||
int matchedCount = 0;
|
||||
while (insnNode != null) {
|
||||
if (insnNode instanceof MethodInsnNode) {
|
||||
@ -76,8 +98,7 @@ public class InvokeLocationMatcher implements LocationMatcher {
|
||||
if (matchCall(methodInsnNode)) {
|
||||
matchedCount++;
|
||||
if (count <= 0 || count == matchedCount) {
|
||||
InvokeLocation invokeLocation = new InvokeLocation(methodInsnNode, count,
|
||||
whenComplete);
|
||||
InvokeLocation invokeLocation = new InvokeLocation(methodInsnNode, count, whenComplete);
|
||||
locations.add(invokeLocation);
|
||||
}
|
||||
}
|
||||
@ -88,16 +109,64 @@ public class InvokeLocationMatcher implements LocationMatcher {
|
||||
return locations;
|
||||
}
|
||||
|
||||
public List<Location> matchForException(MethodProcessor methodProcessor) {
|
||||
List<Location> locations = new ArrayList<Location>();
|
||||
AbstractInsnNode insnNode = methodProcessor.getEnterInsnNode();
|
||||
|
||||
MethodNode methodNode = methodProcessor.getMethodNode();
|
||||
|
||||
List<MethodInsnNode> methodInsnNodes = new ArrayList<MethodInsnNode>();
|
||||
|
||||
int matchedCount = 0;
|
||||
while (insnNode != null) {
|
||||
if (insnNode instanceof MethodInsnNode) {
|
||||
MethodInsnNode methodInsnNode = (MethodInsnNode) insnNode;
|
||||
|
||||
if (matchCall(methodInsnNode)) {
|
||||
matchedCount++;
|
||||
if (count <= 0 || count == matchedCount) {
|
||||
methodInsnNodes.add(methodInsnNode);
|
||||
}
|
||||
}
|
||||
}
|
||||
insnNode = insnNode.getNext();
|
||||
}
|
||||
|
||||
// insert try/catch
|
||||
for (MethodInsnNode methodInsnNode : methodInsnNodes) {
|
||||
TryCatchBlock tryCatchBlock = new TryCatchBlock(methodNode);
|
||||
|
||||
InsnList toInsert = new InsnList();
|
||||
|
||||
LabelNode gotoDest = new LabelNode();
|
||||
|
||||
LabelNode startLabelNode = tryCatchBlock.getStartLabelNode();
|
||||
LabelNode endLabelNode = tryCatchBlock.getEndLabelNode();
|
||||
|
||||
toInsert.add(new JumpInsnNode(Opcodes.GOTO, gotoDest));
|
||||
toInsert.add(endLabelNode);
|
||||
AsmOpUtils.throwException(toInsert);
|
||||
locations.add(new InvokeExceptionExitLocation(methodInsnNode, endLabelNode));
|
||||
|
||||
toInsert.add(gotoDest);
|
||||
|
||||
methodNode.instructions.insertBefore(methodInsnNode, startLabelNode);
|
||||
methodNode.instructions.insert(methodInsnNode, toInsert);
|
||||
|
||||
tryCatchBlock.sort();
|
||||
}
|
||||
|
||||
return locations;
|
||||
}
|
||||
|
||||
private boolean matchCall(MethodInsnNode methodInsnNode) {
|
||||
|
||||
if(methodName == null || methodName.isEmpty()) {
|
||||
return true;
|
||||
|
||||
if (methodName != null && !methodName.isEmpty()) {
|
||||
if (!this.methodName.equals(methodInsnNode.name)) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if (!this.methodName.equals(methodInsnNode.name)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
if (!excludes.isEmpty()) {
|
||||
String ownerClassName = Type.getObjectType(methodInsnNode.owner).getClassName();
|
||||
for (String exclude : excludes) {
|
||||
|
@ -205,7 +205,7 @@ public abstract class Location {
|
||||
/**
|
||||
* location identifying a method invocation trigger point
|
||||
*/
|
||||
public static class InvokeLocation extends Location {
|
||||
public static class InvokeLocation extends Location implements MethodInsnNodeWare {
|
||||
|
||||
/**
|
||||
* count identifying which invocation should be taken as the trigger point. if
|
||||
@ -216,7 +216,7 @@ public abstract class Location {
|
||||
public InvokeLocation(MethodInsnNode insnNode, int count, boolean whenComplete) {
|
||||
super(insnNode, whenComplete);
|
||||
this.count = count;
|
||||
this.stackNeedSave = true;
|
||||
this.stackNeedSave = false;
|
||||
}
|
||||
|
||||
@Override
|
||||
@ -313,34 +313,43 @@ public abstract class Location {
|
||||
boolean isStatic = AsmUtils.isStatic(methodInsnNode);
|
||||
Type[] argumentTypes = methodType.getArgumentTypes();
|
||||
|
||||
// 如果是非static,则存放到数组的index要多 1
|
||||
AsmOpUtils.push(instructions, argumentTypes.length + (isStatic ? 0 : 1));
|
||||
AsmOpUtils.newArray(instructions, AsmOpUtils.OBJECT_TYPE);
|
||||
LocalVariableNode invokeArgsVariableNode = methodProcessor.initInvokeArgsVariableNode();
|
||||
AsmOpUtils.storeVar(instructions, AsmOpUtils.OBJECT_ARRAY_TYPE, invokeArgsVariableNode.index);
|
||||
//保存到 var里,再从var取出放到数组里
|
||||
for(int i = argumentTypes.length - 1; i >= 0 ; --i) {
|
||||
LocalVariableNode methodInvokeArgVar = methodProcessor.addInterceptorLocalVariable("__" + i, argumentTypes[i].getDescriptor());
|
||||
AsmOpUtils.storeVar(instructions, argumentTypes[i], methodInvokeArgVar.index);
|
||||
}
|
||||
// 保存this到 var
|
||||
LocalVariableNode methodInvokeThis = methodProcessor.addInterceptorLocalVariable("__invokemethodthis", AsmOpUtils.OBJECT_TYPE.getDescriptor());
|
||||
AsmOpUtils.storeVar(instructions, AsmOpUtils.OBJECT_TYPE, methodInvokeThis.index);
|
||||
|
||||
// // 如果是非static,则存放到数组的index要多 1
|
||||
// AsmOpUtils.push(instructions, argumentTypes.length + (isStatic ? 0 : 1));
|
||||
// AsmOpUtils.newArray(instructions, AsmOpUtils.OBJECT_TYPE);
|
||||
// LocalVariableNode invokeArgsVariableNode = methodProcessor.initInvokeArgsVariableNode();
|
||||
// AsmOpUtils.storeVar(instructions, AsmOpUtils.OBJECT_ARRAY_TYPE, invokeArgsVariableNode.index);
|
||||
|
||||
// 从invoke的参数的后面,一个个存到数组里
|
||||
for(int i = argumentTypes.length - 1; i >= 0 ; --i) {
|
||||
AsmOpUtils.loadVar(instructions, AsmOpUtils.OBJECT_ARRAY_TYPE, invokeArgsVariableNode.index);
|
||||
|
||||
AsmOpUtils.swap(instructions, argumentTypes[i], AsmOpUtils.OBJECT_ARRAY_TYPE);
|
||||
// 如果是非static,则存放到数组的index要多 1
|
||||
AsmOpUtils.push(instructions, i + (isStatic ? 0 : 1));
|
||||
AsmOpUtils.swap(instructions, argumentTypes[i], Type.INT_TYPE);
|
||||
|
||||
AsmOpUtils.box(instructions, argumentTypes[i]);
|
||||
AsmOpUtils.arrayStore(instructions, AsmOpUtils.OBJECT_TYPE);
|
||||
|
||||
}
|
||||
// for(int i = argumentTypes.length - 1; i >= 0 ; --i) {
|
||||
// AsmOpUtils.loadVar(instructions, AsmOpUtils.OBJECT_ARRAY_TYPE, invokeArgsVariableNode.index);
|
||||
//
|
||||
// AsmOpUtils.swap(instructions, argumentTypes[i], AsmOpUtils.OBJECT_ARRAY_TYPE);
|
||||
// // 如果是非static,则存放到数组的index要多 1
|
||||
// AsmOpUtils.push(instructions, i + (isStatic ? 0 : 1));
|
||||
// AsmOpUtils.swap(instructions, argumentTypes[i], Type.INT_TYPE);
|
||||
//
|
||||
// AsmOpUtils.box(instructions, argumentTypes[i]);
|
||||
// AsmOpUtils.arrayStore(instructions, AsmOpUtils.OBJECT_TYPE);
|
||||
//
|
||||
// }
|
||||
// 处理this
|
||||
if(!isStatic) {
|
||||
AsmOpUtils.loadVar(instructions, AsmOpUtils.OBJECT_ARRAY_TYPE, invokeArgsVariableNode.index);
|
||||
|
||||
AsmOpUtils.swap(instructions, AsmOpUtils.OBJECT_TYPE, AsmOpUtils.OBJECT_ARRAY_TYPE);
|
||||
AsmOpUtils.push(instructions, 0);
|
||||
AsmOpUtils.swap(instructions, AsmOpUtils.OBJECT_TYPE, Type.INT_TYPE);
|
||||
AsmOpUtils.arrayStore(instructions, AsmOpUtils.OBJECT_TYPE);
|
||||
}
|
||||
// if(!isStatic) {
|
||||
// AsmOpUtils.loadVar(instructions, AsmOpUtils.OBJECT_ARRAY_TYPE, invokeArgsVariableNode.index);
|
||||
//
|
||||
// AsmOpUtils.swap(instructions, AsmOpUtils.OBJECT_TYPE, AsmOpUtils.OBJECT_ARRAY_TYPE);
|
||||
// AsmOpUtils.push(instructions, 0);
|
||||
// AsmOpUtils.swap(instructions, AsmOpUtils.OBJECT_TYPE, Type.INT_TYPE);
|
||||
// AsmOpUtils.arrayStore(instructions, AsmOpUtils.OBJECT_TYPE);
|
||||
// }
|
||||
|
||||
}else {
|
||||
throw new IllegalArgumentException("location is not a InvokeLocation, location: " + location);
|
||||
@ -363,25 +372,36 @@ public abstract class Location {
|
||||
boolean isStatic = AsmUtils.isStatic(methodInsnNode);
|
||||
Type[] argumentTypes = methodType.getArgumentTypes();
|
||||
|
||||
if(!isStatic) {
|
||||
// 取出this
|
||||
AsmOpUtils.loadVar(instructions, AsmOpUtils.OBJECT_ARRAY_TYPE, invokeArgsVariableNode.index);
|
||||
AsmOpUtils.push(instructions, 0);
|
||||
AsmOpUtils.arrayLoad(instructions, AsmOpUtils.OBJECT_TYPE);
|
||||
AsmOpUtils.checkCast(instructions, Type.getObjectType(methodInsnNode.owner));
|
||||
// 从var里取回this
|
||||
LocalVariableNode methodInvokeThis = methodProcessor.findLocalVariableLabel("__invokemethodthis");
|
||||
AsmOpUtils.loadVar(instructions, AsmOpUtils.OBJECT_TYPE, methodInvokeThis.index);
|
||||
AsmOpUtils.checkCast(instructions, Type.getObjectType(methodInsnNode.owner));
|
||||
|
||||
// 从 var里取出原来的数据,放回栈上
|
||||
for(int i = 0; i < argumentTypes.length; ++i) {
|
||||
LocalVariableNode methodInvokeArgVar = methodProcessor.findLocalVariableLabel("__" + i);
|
||||
AsmOpUtils.loadVar(instructions, argumentTypes[i], methodInvokeArgVar.index);
|
||||
}
|
||||
|
||||
for(int i = 0; i < argumentTypes.length; ++i) {
|
||||
AsmOpUtils.loadVar(instructions, AsmOpUtils.OBJECT_ARRAY_TYPE, invokeArgsVariableNode.index);
|
||||
AsmOpUtils.push(instructions, i + (isStatic ? 0 : 1));
|
||||
AsmOpUtils.arrayLoad(instructions, AsmOpUtils.OBJECT_TYPE);
|
||||
// TODO 这里直接 unbox 就可以了??unbox里带有 check cast
|
||||
if(AsmOpUtils.needBox(argumentTypes[i])) {
|
||||
AsmOpUtils.unbox(instructions, argumentTypes[i]);
|
||||
}else {
|
||||
AsmOpUtils.checkCast(instructions, argumentTypes[i]);
|
||||
}
|
||||
}
|
||||
// if(!isStatic) {
|
||||
// // 取出this
|
||||
// AsmOpUtils.loadVar(instructions, AsmOpUtils.OBJECT_ARRAY_TYPE, invokeArgsVariableNode.index);
|
||||
// AsmOpUtils.push(instructions, 0);
|
||||
// AsmOpUtils.arrayLoad(instructions, AsmOpUtils.OBJECT_TYPE);
|
||||
// AsmOpUtils.checkCast(instructions, Type.getObjectType(methodInsnNode.owner));
|
||||
// }
|
||||
//
|
||||
// for(int i = 0; i < argumentTypes.length; ++i) {
|
||||
// AsmOpUtils.loadVar(instructions, AsmOpUtils.OBJECT_ARRAY_TYPE, invokeArgsVariableNode.index);
|
||||
// AsmOpUtils.push(instructions, i + (isStatic ? 0 : 1));
|
||||
// AsmOpUtils.arrayLoad(instructions, AsmOpUtils.OBJECT_TYPE);
|
||||
// // TODO 这里直接 unbox 就可以了??unbox里带有 check cast
|
||||
// if(AsmOpUtils.needBox(argumentTypes[i])) {
|
||||
// AsmOpUtils.unbox(instructions, argumentTypes[i]);
|
||||
// }else {
|
||||
// AsmOpUtils.checkCast(instructions, argumentTypes[i]);
|
||||
// }
|
||||
// }
|
||||
|
||||
}else {
|
||||
throw new IllegalArgumentException("location is not a InvokeLocation, location: " + location);
|
||||
@ -399,6 +419,11 @@ public abstract class Location {
|
||||
return stackSaver;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MethodInsnNode methodInsnNode() {
|
||||
return (MethodInsnNode) insnNode;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@ -606,8 +631,7 @@ public abstract class Location {
|
||||
/**
|
||||
* location identifying a method exceptional exit trigger point
|
||||
*/
|
||||
public static class ExceptionExitLocation extends Location {
|
||||
|
||||
public static class ExceptionExitLocation extends Location{
|
||||
public ExceptionExitLocation(AbstractInsnNode insnNode) {
|
||||
super(insnNode, true);
|
||||
stackNeedSave = true;
|
||||
@ -643,4 +667,50 @@ public abstract class Location {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* location identifying a method exceptional exit trigger point
|
||||
*/
|
||||
public static class InvokeExceptionExitLocation extends Location implements MethodInsnNodeWare {
|
||||
private MethodInsnNode methodInsnNode;
|
||||
|
||||
public InvokeExceptionExitLocation(MethodInsnNode methodInsnNode, AbstractInsnNode insnNode) {
|
||||
super(insnNode, true);
|
||||
stackNeedSave = true;
|
||||
this.methodInsnNode = methodInsnNode;
|
||||
}
|
||||
|
||||
public LocationType getLocationType() {
|
||||
return LocationType.INVOKE_EXCEPTION_EXIT;
|
||||
}
|
||||
|
||||
public StackSaver getStackSaver() {
|
||||
StackSaver stackSaver = new StackSaver() {
|
||||
|
||||
@Override
|
||||
public void store(InsnList instructions, BindingContext bindingContext) {
|
||||
LocalVariableNode throwVariableNode = bindingContext.getMethodProcessor().initThrowVariableNode();
|
||||
AsmOpUtils.storeVar(instructions, Type.getType(Throwable.class), throwVariableNode.index);
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void load(InsnList instructions, BindingContext bindingContext) {
|
||||
LocalVariableNode throwVariableNode = bindingContext.getMethodProcessor().initThrowVariableNode();
|
||||
AsmOpUtils.loadVar(instructions, Type.getType(Throwable.class), throwVariableNode.index);
|
||||
}
|
||||
|
||||
@Override
|
||||
public Type getType(BindingContext bindingContext) {
|
||||
return Type.getType(Throwable.class);
|
||||
}
|
||||
|
||||
};
|
||||
return stackSaver;
|
||||
}
|
||||
|
||||
@Override
|
||||
public MethodInsnNode methodInsnNode() {
|
||||
return methodInsnNode;
|
||||
}
|
||||
}
|
||||
}
|
@ -46,6 +46,11 @@ public enum LocationType {
|
||||
*
|
||||
*/
|
||||
INVOKE_COMPLETED,
|
||||
|
||||
/**
|
||||
* method invoke exception
|
||||
*/
|
||||
INVOKE_EXCEPTION_EXIT,
|
||||
/**
|
||||
* synchronize operation
|
||||
*
|
||||
|
@ -0,0 +1,8 @@
|
||||
package com.taobao.arthas.bytekit.asm.location;
|
||||
|
||||
import com.alibaba.arthas.deps.org.objectweb.asm.tree.MethodInsnNode;
|
||||
|
||||
public interface MethodInsnNodeWare {
|
||||
|
||||
public MethodInsnNode methodInsnNode();
|
||||
}
|
Loading…
Reference in New Issue
Block a user