Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android changing private static final field using Java Reflection?

Tags:

android

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?

like image 649
user1884025 Avatar asked Dec 07 '12 00:12

user1884025


2 Answers

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);
like image 117
Bill Cong Avatar answered Oct 26 '22 23:10

Bill Cong


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);
like image 32
Bateramos Avatar answered Oct 26 '22 22:10

Bateramos