0

I am using reflection exactly according to:

Reflection

But everytime I get this error and I don't know why.

12-02 17:53:58.650: W/System.err(10646): java.lang.NoSuchFieldException: modifiers
12-02 17:53:58.650: W/System.err(10646):    at java.lang.Class.getDeclaredField(Class.java:631)
12-02 17:53:58.650: W/System.err(10646):    at com.example.ref.MainActivity.setFinalStatic(MainActivity.java:56)
12-02 17:53:58.650: W/System.err(10646):    at com.example.ref.MainActivity.onCreate(MainActivity.java:26)
12-02 17:53:58.650: W/System.err(10646):    at android.app.Activity.performCreate(Activity.java:5206)
12-02 17:53:58.650: W/System.err(10646):    at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1083)
12-02 17:53:58.650: W/System.err(10646):    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2064)
12-02 17:53:58.650: W/System.err(10646):    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2125)
12-02 17:53:58.650: W/System.err(10646):    at android.app.ActivityThread.access$600(ActivityThread.java:140)

My code below:

    @Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    Log.i("aaa", "Before = " + securedField);
    try {
        Field stringField = MainActivity.class.getDeclaredField("securedField");
        stringField.setAccessible(true);
        setFinalStatic(stringField, new String("Screwed Data!"));
    } catch (Exception e) {
        e.printStackTrace();
    }
    Log.i("aaa", "After = " + securedField);
}

private void setFinalStatic(Field field, Object newValue) throws Exception {
    field.setAccessible(true);
    Field modifiersField = Field.class.getDeclaredField("modifiers");
    modifiersField.setAccessible(true);
    modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL);
    field.set(null, newValue);
}

Does somebody know where the problem is? Thanks!

Community
  • 1
  • 1
AdaMoOo
  • 427
  • 2
  • 5
  • 12

1 Answers1

2

Take a look at the source code of the android version of java.lang.reflect.Field.

It does not have a private field modifiers. Instead it looks like this

public int getModifiers() {
    return accessFlags & 0xffff;  // mask out bits not used by Java
}

You tried to adapt an implementation detail of the "normal" jvm to the android jvm. Since it is an implementation detail of another jvm it will not work with android.

But what you try to do will not work anyway. Keep in mind that the compiler inlines constants.

This will not work

class Greeting {

    public static final String SALUTATION = "Hello";

    public void greet(String name) {
        System.out.println(SALUTATION + " " + name);
    }
}

public class Main {

    public static void main(String[] args) throws Exception {
        Greeting greeting = new Greeting();
        greeting.greet("John");

        Field declaredField = Greeting.class.getDeclaredField("SALUTATION");
        setFinalStatic(declaredField, "Hey");

        greeting.greet("John");
    }

    private static void setFinalStatic(Field field, Object newValue)
            throws Exception {
        field.setAccessible(true);
        Field modifiersField = Field.class.getDeclaredField("modifiers");
        modifiersField.setAccessible(true);
        modifiersField.setInt(field, field.getModifiers() & ~Modifier.FINAL);
        field.set(null, newValue);
    }

} 

The output will be

Hello John
Hello John

Also take a look at JLS, 13.4.9. final Fields and Constants for details.

René Link
  • 48,224
  • 13
  • 108
  • 140