Replacing the static link method in Java

I have a class, as shown below, with a method that just returns a string, but I want to change what it returns from another class, without hard coding it.

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

Is there any way to do this? I tried BCEL, but that did not change the return value.

Edit: this is for mod. I am trying to make it completely independent of existing code without modifying it.

Thanks.

+4
source share
3 answers

Are you sure you tried BCEL? I created a fully working example 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 
+2
source

You can pass a parameter to a method

  public class Main { getName("newName") } public class Name { public static String getName(String name) { return name; } } 
0
source

You can try adding the -javaagent agent, which will use something like asm or bcel , to change the bytecode of the Name class so that the static method returns another string. A lot of fake testing schemes - for example, powermock or jmockit - can do this.

EDIT : Here is a sample code to get you started. This is javaagent that can modify this public static method that returns a String to return another String constant. For example, for example:

 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 $ 
0
source

All Articles