Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/joomla/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
使用javassist更改代码无效(MethodCall)_Java_Javassist_Java Assist - Fatal编程技术网

使用javassist更改代码无效(MethodCall)

使用javassist更改代码无效(MethodCall),java,javassist,java-assist,Java,Javassist,Java Assist,我有一个简单的功能: public int id() { return 0; } void test() { int a = id(); int b = id(); int c = id(); int d = id(); int e = id(); int f = id(); System.out.println(a+" "+b+" "+c+" "+d+" "+e+" "+f); } 我有这个测试功能: public int

我有一个简单的功能:

 public int id() {
    return 0;
}
void test() {
    int a = id();
    int b = id();
    int c = id();
    int d = id();
    int e = id();
    int f = id();
    System.out.println(a+" "+b+" "+c+" "+d+" "+e+" "+f);
}
我有这个测试功能:

 public int id() {
    return 0;
}
void test() {
    int a = id();
    int b = id();
    int c = id();
    int d = id();
    int e = id();
    int f = id();
    System.out.println(a+" "+b+" "+c+" "+d+" "+e+" "+f);
}
我希望输出是
1,2,3,4,5,6

现在我在
CtMethod
上调用
instrument
,它工作正常

call to id! on line: 57
call to id! on line: 58
call to id! on line: 59
call to id! on line: 60
call to id! on line: 61
call to id! on line: 62
但最终,所有的转换都没有任何效果。 我不知道该怎么办,因为信息太少了

以下是完整的代码:

package doeke.method\u call\u test;
导入java.lang.instrument.Instrumentation;
导入javassist.CannotCompileException;
导入javassist.ClassPool;
导入javassist.CtClass;
导入javassist.CtMethod;
导入javassist.expr.ExprEditor;
导入javassist.expr.MethodCall;
公共类方法调用测试{
静态int-id=1;
公共静态无效预输入(字符串代理、仪器仪表){
试一试{
ClassPool ClassPool=ClassPool.getDefault();
CtClass-CtClass=classPool.getCtClass(“doeke.method\u call\u test.MethodCallTest”);
CtMethod[]methods=ctClass.getDeclaredMethods();
用于(CTCM方法:方法){
厘米仪器(
新ExprEditor(){
public void edit(MethodCall m)抛出CannotCompileException{
if(m.getMethodName().equals(“id”)){
//m.replace(“{$\=“+id+”;}”);
m、 替换(“$\”=1;System.out.println(\“hello?\”);”;
System.out.println(“在线调用id:+m.getLineNumber());
id++;
}
}
}
);
}
inst.retransformClasses(MethodCallTest.class);
}
捕获(例外e){
e、 printStackTrace();
}
}
公共静态void main(字符串[]args){
MethodCallTest mct=新的MethodCallTest();
mct.test();
}
无效测试(){
int a=id();
int b=id();
int c=id();
int d=id();
int e=id();
int f=id();
系统输出打印项次(a+“”+b+“”+c+“”+d+“”+e+“”+f);
}
公共int id(){
返回0;
}
}

不确定如何运行代码,因为通常需要在命令行上使用javaagent启动JVM来注入实例。在下面的示例中,我使用在运行时获取Instrumentation实例

您还必须创建一个返回已修改类的字节码的,您可以通过调用
CtClass.toByteCode()

下面的代码打印此输出:

call to id! on line: 84
call to id! on line: 85
call to id! on line: 86
call to id! on line: 87
call to id! on line: 88
call to id! on line: 89
Transforming [doeke/method_call_test/MethodCallTest]
hello?
hello?
hello?
hello?
hello?
hello?
1 1 1 1 1 1
基本代码:

package doeke.method_call_test;

import java.lang.instrument.ClassFileTransformer;
import java.lang.instrument.IllegalClassFormatException;
import java.lang.instrument.Instrumentation;
import java.security.ProtectionDomain;

import javassist.CannotCompileException;
import javassist.ClassPool;
import javassist.CtClass;
import javassist.CtMethod;
import javassist.expr.ExprEditor;
import javassist.expr.MethodCall;
import net.bytebuddy.agent.ByteBuddyAgent;

public class MethodCallTest {



    static int id = 1;


    public static void premain(String agentArgs, Instrumentation inst) {

        try {

            ClassPool classPool = ClassPool.getDefault();
            CtClass ctClass = classPool.getCtClass("doeke.method_call_test.MethodCallTest");
            CtMethod[] methods = ctClass.getDeclaredMethods();

            for (CtMethod cm : methods) {
                cm.instrument(
                    new ExprEditor() {
                        public void edit(MethodCall m) throws CannotCompileException {
                            if (m.getMethodName().equals("id")) {

                                // m.replace("{ $_ = "+id+"; }");
                                m.replace("$_ = 1; System.out.println(\"hello?\");");

                                System.out.println("call to id! on line: "+m.getLineNumber());

                                id++;
                            }
                        }
                    }
                );
            }
            final byte[] byteCode = ctClass.toBytecode();
            final String rezName = MethodCallTest.class.getName().replace('.', '/');
            final ClassFileTransformer transformer = new ClassFileTransformer() {

                @Override
                public byte[] transform(ClassLoader loader, String className, Class<?> classBeingRedefined,
                        ProtectionDomain protectionDomain, byte[] classfileBuffer) throws IllegalClassFormatException {
                    if (rezName.equals(className)) {
                        System.out.println("Transforming [" + className + "]");
                        return byteCode;
                    }
                    return null;
                }

            };
            inst.addTransformer(transformer, true);
            try {
                inst.retransformClasses(MethodCallTest.class);
            } finally {
                inst.removeTransformer(transformer);
            }
        }
        catch (Exception e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {
            MethodCallTest mct = new MethodCallTest();
            Instrumentation inst = ByteBuddyAgent.install();
            MethodCallTest.premain("", inst);
            mct.test();
    }


    void test() {
        int a = id();
        int b = id();
        int c = id();
        int d = id();
        int e = id();
        int f = id();
        System.out.println(a+" "+b+" "+c+" "+d+" "+e+" "+f);
    }



    public int id() {
        return 0;
    }


}
package doeke.method\u call\u test;
导入java.lang.instrument.ClassFileTransformer;
导入java.lang.instrument.IllegalClassFormatException;
导入java.lang.instrument.Instrumentation;
导入java.security.ProtectionDomain;
导入javassist.CannotCompileException;
导入javassist.ClassPool;
导入javassist.CtClass;
导入javassist.CtMethod;
导入javassist.expr.ExprEditor;
导入javassist.expr.MethodCall;
导入net.bytebuddy.agent.bytebuddy代理;
公共类方法调用测试{
静态int-id=1;
公共静态无效预输入(字符串代理、仪器仪表){
试一试{
ClassPool ClassPool=ClassPool.getDefault();
CtClass-CtClass=classPool.getCtClass(“doeke.method\u call\u test.MethodCallTest”);
CtMethod[]methods=ctClass.getDeclaredMethods();
用于(CTCM方法:方法){
厘米仪器(
新ExprEditor(){
public void edit(MethodCall m)抛出CannotCompileException{
if(m.getMethodName().equals(“id”)){
//m.replace(“{$\=“+id+”;}”);
m、 替换(“$\”=1;System.out.println(\“hello?\”);”;
System.out.println(“在线调用id:+m.getLineNumber());
id++;
}
}
}
);
}
最后一个字节[]字节码=ctClass.toBytecode();
最后一个字符串rezName=MethodCallTest.class.getName().replace('.','/');
最终ClassFileTransformer transformer=新ClassFileTransformer(){
@凌驾
公共字节[]转换(类加载器、字符串类名、类被重新定义、,
ProtectionDomain ProtectionDomain,字节[]classfileBuffer)引发IllegalClassFormatException{
if(rezName.equals(className)){
System.out.println(“转换[“+className+”]);
返回字节码;
}
返回null;
}
};
仪器添加变压器(变压器,真实);
试一试{
inst.retransformClasses(MethodCallTest.class);
}最后{
仪表拆卸变压器(变压器);
}
}
捕获(例外e){
e、 printStackTrace();
}
}
公共静态void main(字符串[]args){
MethodCallTest mct=新的MethodCallTest();
Instrumentation inst=ByteBuddyAgent.install();
方法:普莱曼试验(“,inst);
mct.test();
}
无效测试(){
int a=id();
int b=id();
int c=id();
int d=id();
int e=id();
int f=id();
系统输出打印项次(a+“”+b+“”+c+“”+d+“”+e+“”+f);
}
公共int id(){
返回0;
}
}