mirror of https://github.com/alibaba/arthas.git
support InstrumentApi.invokeOrigin(). #573
parent
77460d071f
commit
1f306c5a50
@ -0,0 +1,52 @@
|
||||
package com.taobao.arthas.bytekit.asm.inst.impl;
|
||||
|
||||
import org.objectweb.asm.Label;
|
||||
import org.objectweb.asm.tree.MethodNode;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author hengyunabc 2019-03-18
|
||||
*
|
||||
*/
|
||||
public class MethodReplaceResult {
|
||||
|
||||
private boolean success;
|
||||
|
||||
private Label start;
|
||||
private Label end;
|
||||
|
||||
private MethodNode methodNode;
|
||||
|
||||
public Label getStart() {
|
||||
return start;
|
||||
}
|
||||
|
||||
public void setStart(Label start) {
|
||||
this.start = start;
|
||||
}
|
||||
|
||||
public Label getEnd() {
|
||||
return end;
|
||||
}
|
||||
|
||||
public void setEnd(Label end) {
|
||||
this.end = end;
|
||||
}
|
||||
|
||||
public MethodNode getMethodNode() {
|
||||
return methodNode;
|
||||
}
|
||||
|
||||
public void setMethodNode(MethodNode methodNode) {
|
||||
this.methodNode = methodNode;
|
||||
}
|
||||
|
||||
public boolean isSuccess() {
|
||||
return success;
|
||||
}
|
||||
|
||||
public void setSuccess(boolean success) {
|
||||
this.success = success;
|
||||
}
|
||||
|
||||
}
|
@ -1,21 +1,18 @@
|
||||
package com.taobao.arthas.bytekit.asm.inst;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
public class InstDemo {
|
||||
|
||||
public int returnInt(int i) {
|
||||
return 9998;
|
||||
}
|
||||
|
||||
public static int returnIntStatic(int i) {
|
||||
return 9998;
|
||||
}
|
||||
public int returnInt(int i) {
|
||||
System.out.println(new Object[] { i });
|
||||
return 9998;
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
Date date = new Date(1551168643);
|
||||
public static void onEnter(Object[] args) {
|
||||
System.out.println(args);
|
||||
}
|
||||
|
||||
System.err.println(date.toLocaleString());
|
||||
public static int returnIntStatic(int i) {
|
||||
return 9998;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,5 +1,77 @@
|
||||
package com.taobao.arthas.bytekit.asm.inst;
|
||||
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
* @author hengyunabc 2019-03-13
|
||||
*
|
||||
*/
|
||||
public class InvokeOriginDemo {
|
||||
|
||||
public void returnVoid() {
|
||||
}
|
||||
|
||||
public Void returnVoidObject() {
|
||||
int i = 0;
|
||||
try {
|
||||
int parseInt = Integer.parseInt("1000");
|
||||
i += parseInt;
|
||||
} catch (Exception e) {
|
||||
System.err.println(i + " " + e);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
public int returnInt(int i) {
|
||||
return 9998;
|
||||
}
|
||||
|
||||
public int returnIntToObject(int i) {
|
||||
|
||||
return 9998;
|
||||
}
|
||||
|
||||
public int returnIntToInteger(int i) {
|
||||
|
||||
return 9998;
|
||||
}
|
||||
|
||||
public static int returnIntStatic(int i) {
|
||||
return 9998;
|
||||
}
|
||||
|
||||
public long returnLong() {
|
||||
return 9998L;
|
||||
}
|
||||
|
||||
public long returnLongToObject() {
|
||||
return 9998L;
|
||||
}
|
||||
|
||||
public String[] returnStrArray() {
|
||||
String[] result = new String[] {"abc", "xyz" , "ufo"};
|
||||
return result;
|
||||
}
|
||||
|
||||
public String[] returnStrArrayWithArgs(int i, String s, long l) {
|
||||
String[] result = new String[] {"abc" + i, "xyz" + s , "ufo" + l};
|
||||
return result;
|
||||
}
|
||||
|
||||
public String returnStr() {
|
||||
return new Date().toString();
|
||||
}
|
||||
|
||||
public Object returnObject() {
|
||||
return InvokeOriginDemo.class;
|
||||
}
|
||||
|
||||
|
||||
public int recursive(int i) {
|
||||
if (i == 1) {
|
||||
return 1;
|
||||
}
|
||||
return i + recursive(i - 1);
|
||||
}
|
||||
}
|
||||
|
@ -1,5 +1,85 @@
|
||||
package com.taobao.arthas.bytekit.asm.inst;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author hengyunabc 2019-03-18
|
||||
*
|
||||
*/
|
||||
public class InvokeOriginDemo_APM {
|
||||
|
||||
public void returnVoid() {
|
||||
Object o = InstrumentApi.invokeOrigin();
|
||||
System.out.println(o);
|
||||
}
|
||||
|
||||
public Void returnVoidObject() {
|
||||
Void v = InstrumentApi.invokeOrigin();
|
||||
System.out.println(v);
|
||||
return v;
|
||||
}
|
||||
|
||||
public int returnInt(int i) {
|
||||
System.out.println("before");
|
||||
int value = InstrumentApi.invokeOrigin();
|
||||
System.out.println("after");
|
||||
return value + 123;
|
||||
}
|
||||
|
||||
public int returnIntToObject(int i) {
|
||||
Object value = InstrumentApi.invokeOrigin();
|
||||
return 9998 + (Integer) value;
|
||||
}
|
||||
|
||||
public int returnIntToInteger(int i) {
|
||||
|
||||
Integer ixx = InstrumentApi.invokeOrigin();
|
||||
|
||||
return ixx + 9998;
|
||||
}
|
||||
|
||||
public static int returnIntStatic(int i) {
|
||||
int result = InstrumentApi.invokeOrigin();
|
||||
return 9998 + result;
|
||||
}
|
||||
|
||||
public long returnLong() {
|
||||
long result = InstrumentApi.invokeOrigin();
|
||||
return 9998L + result;
|
||||
}
|
||||
|
||||
public long returnLongToObject() {
|
||||
Long lll = InstrumentApi.invokeOrigin();
|
||||
return 9998L + lll;
|
||||
}
|
||||
|
||||
public String[] returnStrArray() {
|
||||
String[] result = InstrumentApi.invokeOrigin();
|
||||
System.err.println(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
public String[] returnStrArrayWithArgs(int i, String s, long l) {
|
||||
System.out.println(i);
|
||||
String[] result = InstrumentApi.invokeOrigin();
|
||||
result[0] = "fff";
|
||||
return result;
|
||||
}
|
||||
|
||||
public String returnStr() {
|
||||
System.err.println("ssss");
|
||||
Object result = InstrumentApi.invokeOrigin();
|
||||
return "hello" + result;
|
||||
}
|
||||
|
||||
public Object returnObject() {
|
||||
InstrumentApi.invokeOrigin();
|
||||
return InvokeOriginDemo.class;
|
||||
}
|
||||
|
||||
public int recursive(int i) {
|
||||
int result = InstrumentApi.invokeOrigin();
|
||||
|
||||
System.err.println(result);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
@ -0,0 +1,178 @@
|
||||
package com.taobao.arthas.bytekit.asm.inst;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.assertj.core.api.Assertions;
|
||||
import org.junit.Before;
|
||||
import org.junit.BeforeClass;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.TestName;
|
||||
import org.objectweb.asm.Type;
|
||||
import org.objectweb.asm.tree.ClassNode;
|
||||
import org.objectweb.asm.tree.MethodNode;
|
||||
|
||||
import com.taobao.arthas.bytekit.asm.inst.impl.InstrumentImpl;
|
||||
import com.taobao.arthas.bytekit.utils.AsmUtils;
|
||||
import com.taobao.arthas.bytekit.utils.Decompiler;
|
||||
import com.taobao.arthas.bytekit.utils.VerifyUtils;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author hengyunabc 2019-03-18
|
||||
*
|
||||
*/
|
||||
public class InvokeOriginTest {
|
||||
|
||||
ClassNode apmClassNode;
|
||||
ClassNode originClassNode;
|
||||
|
||||
ClassNode targetClassNode;
|
||||
|
||||
@Rule
|
||||
public TestName testName = new TestName();
|
||||
|
||||
@BeforeClass
|
||||
public static void beforeClass() throws IOException {
|
||||
|
||||
}
|
||||
|
||||
@Before
|
||||
public void before() throws IOException {
|
||||
apmClassNode = AsmUtils.loadClass(InvokeOriginDemo_APM.class);
|
||||
originClassNode = AsmUtils.loadClass(InvokeOriginDemo.class);
|
||||
|
||||
byte[] renameClass = AsmUtils.renameClass(AsmUtils.toBytes(apmClassNode),
|
||||
Type.getObjectType(originClassNode.name).getClassName());
|
||||
|
||||
apmClassNode = AsmUtils.toClassNode(renameClass);
|
||||
|
||||
targetClassNode = AsmUtils.copy(originClassNode);
|
||||
}
|
||||
|
||||
private Object replace(String methodName) throws Exception {
|
||||
System.err.println(methodName);
|
||||
for (MethodNode methodNode : apmClassNode.methods) {
|
||||
if (methodNode.name.equals(methodName)) {
|
||||
methodNode = AsmUtils.removeLineNumbers(methodNode);
|
||||
// 从原来的类里查找对应的函数
|
||||
MethodNode findMethod = AsmUtils.findMethod(originClassNode.methods, methodNode);
|
||||
if (findMethod != null) {
|
||||
MethodNode methodNode2 = InstrumentImpl.replaceInvokeOrigin(originClassNode.name, findMethod,
|
||||
methodNode);
|
||||
|
||||
System.err.println(Decompiler.toString(methodNode2));
|
||||
|
||||
AsmUtils.replaceMethod(targetClassNode, methodNode2);
|
||||
|
||||
} else {
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
byte[] resutlBytes = AsmUtils.toBytes(targetClassNode);
|
||||
|
||||
System.err.println("=================");
|
||||
|
||||
System.err.println(Decompiler.decompile(resutlBytes));
|
||||
|
||||
// System.err.println(AsmUtils.toASMCode(resutlBytes));
|
||||
|
||||
VerifyUtils.asmVerify(resutlBytes);
|
||||
return VerifyUtils.instanceVerity(resutlBytes);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test_returnVoid() throws Exception {
|
||||
String methodName = testName.getMethodName().substring("test_".length());
|
||||
Object object = replace(methodName);
|
||||
|
||||
Assertions.assertThat(VerifyUtils.invoke(object, methodName)).isEqualTo(null);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test_returnVoidObject() throws Exception {
|
||||
String methodName = testName.getMethodName().substring("test_".length());
|
||||
Object object = replace(methodName);
|
||||
Assertions.assertThat(VerifyUtils.invoke(object, methodName)).isEqualTo(null);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test_returnInt() throws Exception {
|
||||
String methodName = testName.getMethodName().substring("test_".length());
|
||||
Object object = replace(methodName);
|
||||
Assertions.assertThat(VerifyUtils.invoke(object, methodName, 123)).isEqualTo(9998 + 123);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test_returnIntToObject() throws Exception {
|
||||
String methodName = testName.getMethodName().substring("test_".length());
|
||||
Object object = replace(methodName);
|
||||
Assertions.assertThat(VerifyUtils.invoke(object, methodName, 123)).isEqualTo(9998 + 9998);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test_returnIntToInteger() throws Exception {
|
||||
String methodName = testName.getMethodName().substring("test_".length());
|
||||
Object object = replace(methodName);
|
||||
Assertions.assertThat(VerifyUtils.invoke(object, methodName, 123)).isEqualTo(9998 + 9998);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test_returnIntStatic() throws Exception {
|
||||
String methodName = testName.getMethodName().substring("test_".length());
|
||||
Object object = replace(methodName);
|
||||
Assertions.assertThat(VerifyUtils.invoke(object, methodName, 123)).isEqualTo(9998 + 9998);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test_returnLong() throws Exception {
|
||||
String methodName = testName.getMethodName().substring("test_".length());
|
||||
Object object = replace(methodName);
|
||||
Assertions.assertThat(VerifyUtils.invoke(object, methodName)).isEqualTo(9998L + 9998);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test_returnLongToObject() throws Exception {
|
||||
String methodName = testName.getMethodName().substring("test_".length());
|
||||
Object object = replace(methodName);
|
||||
Assertions.assertThat(VerifyUtils.invoke(object, methodName)).isEqualTo(9998L + 9998);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test_returnStrArray() throws Exception {
|
||||
String methodName = testName.getMethodName().substring("test_".length());
|
||||
Object object = replace(methodName);
|
||||
Assertions.assertThat(VerifyUtils.invoke(object, methodName)).isEqualTo(new String[] { "abc", "xyz", "ufo" });
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test_returnStrArrayWithArgs() throws Exception {
|
||||
String methodName = testName.getMethodName().substring("test_".length());
|
||||
Object object = replace(methodName);
|
||||
Assertions.assertThat(VerifyUtils.invoke(object, methodName, 123, "sss", 777L))
|
||||
.isEqualTo(new Object[] { "fff", "xyz" + "sss", "ufo" + 777 });
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test_returnStr() throws Exception {
|
||||
String methodName = testName.getMethodName().substring("test_".length());
|
||||
Object object = replace(methodName);
|
||||
Assertions.assertThat(VerifyUtils.invoke(object, methodName)).asString().startsWith("hello");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test_returnObject() throws Exception {
|
||||
String methodName = testName.getMethodName().substring("test_".length());
|
||||
Object object = replace(methodName);
|
||||
Assertions.assertThat(VerifyUtils.invoke(object, methodName)).isEqualTo(object.getClass());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void test_recursive() throws Exception {
|
||||
String methodName = testName.getMethodName().substring("test_".length());
|
||||
Object object = replace(methodName);
|
||||
Assertions.assertThat(VerifyUtils.invoke(object, methodName, 100)).isEqualTo((100 + 1) * 100 / 2);
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue