java中的反射替换静态引用方法

nqwrtyyt  于 2021-07-09  发布在  Java
关注(0)|答案(3)|浏览(288)

我有一个像下面这样的类,它有一个只返回字符串的方法,但是我想修改它从另一个类返回的内容,而不是自己硬编码它。

public class Name {
    public static String getName() {
        return "MyName";
    }
}

有什么办法吗?我试过bcel,但似乎没有改变返回值。
编辑:这是一个模块。我试图使它完全独立于现有的代码,通过不修改它。
谢谢。

tvmytwxo

tvmytwxo1#

你确定你试过bcel吗?我在这里创建了一个完全有效的示例。

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
ffx8fchx

ffx8fchx2#

您可以尝试添加 -javaagent 代理,它将使用类似asm或bcel的内容来修改 Name 类,以便静态方法将返回另一个字符串。许多模拟测试框架(例如powermock或jmockit)都可以做到这一点。
编辑:这里是一些示例代码,让你开始。这是一个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
$
6yt4nkrj

6yt4nkrj3#

可以将参数传递到方法中

public class Main {
        getName("newName")
    }

public class Name {
    public static String getName(String name) {
        return name;
    }
}

相关问题