1

我正在尝试使用 ByteCode Engineering Library (by Apache) 从另一个类生成(和修改)输出类的代码。

String class_name = c_gen.getClassName();
    Method[] Methods = c_gen.getMethods();

    for (int i=0;i<Methods.length;i++)
    {
        MethodGen m_gen = new MethodGen(Methods[i], class_name, cpg);
        InstructionList il = m_gen.getInstructionList();
        InstructionHandle h;
           il.insert(h,factory.createInvoke("ClassName","printSomething",   Type.VOID,new Type[]{Type.STRING}, INVOKESTATIC));
    }

所以我试图从 ClassName 为每个方法调用 printSomething。问题是我不知道如何将字符串参数实际传递给方法 printSomething

4

1 回答 1

1

您需要在调用静态之前将字符串参数推送到堆栈上。这是通过LDC操作码完成的。就像是:

il.insert( new LDC(cpg.addString("MyString")));

大纲如下所示:

JavaClass clazz = Repository.lookupClass( class_name );
ClassGen c_gen = new ClassGen( clazz );
ConstantPoolGen cpg = new ConstantPoolGen( clazz.getConstantPool() );
InstructionFactory factory = new InstructionFactory( c_gen, cpg );

Methods [] methods = clazz.getMethods();

for ( int i = 0; i < methods.length; i ++ )
{
    if ( m.isAbstract() || m.isNative() || .... )
        continue;

    MethodGen m_gen = new MethodGen( methods[i], class_name, cpg );
    InstructionList il = m_gen.getInstructionList();

    il.insert( factory.createInvoke("ClassName", "printSomething",
        Type.VOID, new Type[]{Type.STRING}, INVOKESTATIC) );
    il.insert( factory.createPush( "StringToPrint" ) );

    methods[i] = m_gen.getMethod();
}

clazz.setConstantPool( cpg.getFinalConstantPool() );
clazz.setMethods( methods ); // might be redundant

clazz.dump( new File( .... ) );

几点注意事项:

  • 由于我们正在插入,因此每个插入都将添加到该方法之前。这就是为什么我们首先插入指令操作码,然后插入参数(反向),这样实际的序列将是ldc #stringref; invokestatic #methodref.
  • 我们需要用修改后的版本替换 ConstantPool 和 Methods。
于 2015-10-31T22:25:24.333 回答