user1884025
user1884025

Reputation: 111

Android changing private static final field using Java Reflection?

I want to set "NO_CACHE" to be newValue. Here is my code:

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

But running this code on Android produces the following error:

java.lang.NoSuchFieldException: modifiers

I find modifiers is a field in the Field class in Java, but it is not a field in the Field class on Android.

This is Java Field class code:

http://www.docjar.com/html/api/java/lang/reflect/Field.java.html

This is Android Field class code:

http://www.oschina.net/code/explore/android-2.2-froyo/java/lang/reflect/Field.java

The above code in Java can work, but it does not work on the Android platform.

How do I fix this?

Upvotes: 11

Views: 4560

Answers (2)

Bill Cong
Bill Cong

Reputation: 81

I have tried the solutions above and get the correct way to modify static and final field in Android,here is the code works in Android 7.0

Field booleanField = Boolean.class.getField("FALSE");
booleanField.setAccessible(true);
Field modifiersField = Field.class.getDeclaredField("accessFlags");
modifiersField.setAccessible(true);
modifiersField.setInt(field,field.getModifiers() & ~Modifier.FINAL);
booleanField.set(null, true);

Upvotes: 7

Bateramos
Bateramos

Reputation: 156

Android actually doesn't use JDK source code. It's something very alike but not the same.

In Java, modifiers are of type java.lang.reflection.Field, but in Android there is no such type. Android implemented a system which uses an integer and the name of the Field to validate it's modifiers, by calling a native method.

I think a private static final field will have slot-1 and a private field will have the value 3. If you wish to change a private static final field, just change the slot to 3 before setting the value.

Field booleanField = Boolean.class.getField("FALSE");
booleanField.setAccessible(true);

Field slotField = Field.class.getDeclaredField("slot");
slotField.setAccessible(true);
slotField.set(booleanField, 3);

booleanField.set(Boolean.FALSE, true);

Upvotes: 3

Related Questions