我有一个像下面这样的类,只有一个返回String的方法,但我想修改它从另一个类返回的内容,而不是自己硬编码。
public class Name {
public static String getName() {
return "MyName";
}
}
有没有办法做到这一点?我尝试过BCEL,但似乎没有改变返回值。
编辑:这是一个mod。我试图通过不修改它来使它与现有代码完全无关。
感谢。
答案 0 :(得分:2)
你确定你是否尝试过BCEL?我创建了一个完整的示例here。
JavaClass target;
try {
target = Repository.lookupClass("Target");
} catch (final ClassNotFoundException ex) {
throw new RuntimeException("unable to resolve Target", ex);
}
final ClassGen targetGen = new ClassGen(target);
final ConstantPoolGen pool = targetGen.getConstantPool();
final ConstantMethodref ref = (ConstantMethodref) pool.getConstant(
pool.lookupMethodref("Name", "getName", "()Ljava/lang/String;"));
ref.setClassIndex(pool.lookupClass("Target"));
ref.setNameAndTypeIndex(pool.addNameAndType("$Name$getName", "()Ljava/lang/String;"));
final InstructionList code = new InstructionList();
final InstructionFactory factory = new InstructionFactory(targetGen, pool);
code.append(factory.createConstant("overriden-name"));
code.append(factory.createReturn(Type.STRING));
code.setPositions();
final MethodGen methodGen = new MethodGen(
Constants.ACC_PRIVATE | Constants.ACC_SYNTHETIC | Constants.ACC_STATIC,
Type.STRING, new Type[0], new String[0], "$Name$getName", "Target",
code, pool);
methodGen.setMaxLocals(0);
methodGen.setMaxStack(1);
targetGen.addMethod(methodGen.getMethod());
try {
targetGen.getJavaClass().dump("Target.class");
} catch (final IOException ex) {
throw new RuntimeException("unable to save Target", ex);
}
C:\dev\scrap>javac Target.java C:\dev\scrap>java Target original-name C:\dev\scrap>javac -cp .;bcel-6.0.jar Instrumenter.java C:\dev\scrap>java -cp .;bcel-6.0.jar Instrumenter C:\dev\scrap>java Target overriden-name
答案 1 :(得分:0)
您可以将参数传递给方法
public class Main {
getName("newName")
}
public class Name {
public static String getName(String name) {
return name;
}
}
答案 2 :(得分:0)
您可以尝试添加-javaagent
代理,该代理将使用asm或bcel之类的内容来修改Name
类的字节码,以便静态方法返回另一个串。许多模拟测试框架 - 例如powermock或jmockit - 可以做到这一点。
编辑:Here是一些示例代码,可帮助您入门。这是一个javaagent,它可以修改给定的公共静态方法,该方法返回String
以返回另一个常量String
。例如:
public class TestMain
{
public static void main(String[] args)
{
System.out.println(Name.getName());
}
}
class Name
{
public static String getName()
{
return "ORIGINAL";
}
}
$ java -cp build/libs/bciex.jar mycompany.myapp.TestMain
ORIGINAL
$ java -cp build/libs/bciex.jar -javaagent:build/libs/bciex.jar="mycompany.myapp.TestMain|getName|SOME_STRING" mycompany.myapp.TestMain
Agent loaded; will modify [getName] method of classes in [mycompany.myapp.TestMain] to return [SOME_STRING]
SOME_STRING
$