0

Before you read this: I know that the following is a pretty nasty piece of code. I am ashamed of it and will eliminate it as soon as possible but for the time beeing I need to make it work.

In my project (project A) I depend on another project (project B) which is imported via gradle from jcenter.

somewhere in project B there is this class

public class Postfixer{
    static final string postfix = " bad postfix";
    postfix(String input){
        input += postfix;
        /*do something with input*/
    }
}

in project A there ist this functioncall

/*do something*/
System.out.println(new Postfixer().postfix("Hello there"));
/*do even more*/

I really have to replace the postfix before /*do something with input*/

So I did the following

Field postfixField = Postfixer.class.getDeclaredField("postfix");
postfixField .setAccessible(true);
Field modifiersField = Field.class.getDeclaredField("modifiers");
modifiersField.setAccessible(true);
modifiersField.setInt(postfixField, field.getModifiers() & ~Modifier.FINAL);
postfixField.set(null, " better postfix");

It seems to have worked, when i run the code there is no exception at all but the execution of Postfixer is not affected at all. The output of System.out.println(new Postfixer().postfix("Hello there")); is still "Hello there bad postfix"

Do you see any mistake that i could have made? PS: This is horribly simplified. Nearly all of the code I am trying to change is in the form of binaries and all of this happens deep deep down in the callstack far from my own code.

Mr.H.
  • 965
  • 1
  • 10
  • 18
  • 1
    `static final` is a real constant, it get substituted at compile time. To get is use changed, you need to recompile after changing the field (in source) (you can only hack the String instance and change its `value` field - not recommended) – user85421 Aug 22 '19 at 15:18
  • @CarlosHeuberger that is exactly the answer I dreaded. As project B is closed source but with debuginformation, I would have to decompile it, change its value and recompile it. I'd rather do the "not recommended" approach, but how do you do it without a debugger? – Mr.H. Aug 23 '19 at 07:04
  • no need for debugger, source of String should be available with JDK. Basically you must change the field `private final byte[] value;` using reflection, but consider the warning that comes with it: "*This field is trusted by the VM, and is a subject to constant folding if String instance is constant. Overwriting this field after construction will cause problems.*" – user85421 Aug 23 '19 at 10:23
  • @CarlosHeuberger As I understand it a byte[] has a constant length, so there is no way to manipulate it to be a longer String than the original one. – Mr.H. Aug 23 '19 at 12:03
  • @Mr.H. you can change value of final field https://stackoverflow.com/questions/3301635/change-private-static-final-field-using-java-reflection but yea, be sure that it might not work too well. – GotoFinal Aug 29 '19 at 07:11
  • nevermind. I solved it by changing the configuration of the application in order to avoid using the malfunctioning classes. – Mr.H. Sep 12 '19 at 09:59

0 Answers0