Set Private Field Value with Reflection

Set private field value with reflection

To access a private field you need to set Field::setAccessible to true. You can pull the field off the super class. This code works:

Class<?> clazz = Child.class;
Object cc = clazz.newInstance();

Field f1 = cc.getClass().getSuperclass().getDeclaredField("a_field");
f1.setAccessible(true);
f1.set(cc, "reflecting on life");
String str1 = (String) f1.get(cc);
System.out.println("field: " + str1);

What is the shortest, best, cleanest way to set a private field via Reflection in Java?

The "One-Liner"

FieldUtils.writeField(Object target, String fieldName, Object value, boolean forceAccess)

If your Project uses Apache Commons Lang
the shortest way to set a value via reflection is to use the static Method 'writeField' in the class 'org.apache.commons.lang3.reflect.FieldUtils'

The following simple example shows a Bookstore-Object with a field paymentService. The code shows how the private field is set two times with a different value.

import org.apache.commons.lang3.reflect.FieldUtils;

public class Main2 {
public static void main(String[] args) throws IllegalAccessException {
Bookstore bookstore = new Bookstore();

//Just one line to inject the field via reflection
FieldUtils.writeField(bookstore, "paymentService",new Paypal(), true);
bookstore.pay(); // Prints: Paying with: Paypal

//Just one line to inject the field via reflection
FieldUtils.writeField(bookstore, "paymentService",new Visa(), true);
bookstore.pay();// Prints Paying with: Visa
}

public static class Paypal implements PaymentService{}

public static class Visa implements PaymentService{}

public static class Bookstore {
private PaymentService paymentService;
public void pay(){
System.out.println("Paying with: "+ this.paymentService.getClass().getSimpleName());
}
}
}

You can get the lib via maven central:

<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.8.1</version>
</dependency>

Get a private field via reflection, in Java

Change this line

name = (String) myStringField.get(obj.getClass());

to this

name = (String) myStringField.get(obj);

The get method requires an object to access the field of (unless it's a static field)

Set private field of package-private Class from outer package Class with reflection

I could see that the JarVerifier class does not have a default Constructor.
The constructor it has is something like this:-

public JarVerifier(byte rawBytes[]) {
manifestRawBytes = rawBytes;
sigFileSigners = new Hashtable<>();
verifiedSigners = new Hashtable<>();
sigFileData = new Hashtable<>(11);
pendingBlocks = new ArrayList<>();
baos = new ByteArrayOutputStream();
manifestDigests = new ArrayList<>();
}

So, you would have to get the non-default Constructor using reflection and then use it to create the instance. So, your code should be something like this:-

field.setBoolean(clazz.getConstructor(byte[].class).newInstance(new byte[1]), newValue);

Reference for JarVerifier class: https://github.com/netroby/jdk9-dev/blob/master/jdk/src/java.base/share/classes/java/util/jar/JarVerifier.java

Assumption: Your application has the required security permissions to modify access using reflection.

Further reference: Java: newInstance of class that has no default constructor

Setting private fields using Java Reflection

Get all the methods and find the matching one, which has type info about the parameters:

String name;
String value;
Method[] methods = Child.class.getMethods();
for (Method method : methods) {
if (!method.getName().equals(name))
continue;
Class<?> paramType = method.getParameterTypes()[0];
//You will have to figure how to convert the String value to the parameter.
method.invoke(child, paramType.cast(value)); // for example
}

Set value of private field

Try this (inspired by Find a private field with Reflection?):

var prop = s.GetType().GetField("id", System.Reflection.BindingFlags.NonPublic
| System.Reflection.BindingFlags.Instance);
prop.SetValue(s, "new value");

My changes were to use the GetField method - you are accessing a field and not a property, and to or NonPublic with Instance.

Reflection - getting private field value

val currentTrainingField = viewModel.javaClass.getDeclaredField("currentTraining")
currentTrainingField.isAccessible = true

val currentTraining = currentTrainingField.get(viewModel)

You relaxed the field's scope but you should access the value of that field on a specfic object, here viewModel.

How to read the value of a private field from a different class in Java?

In order to access private fields, you need to get them from the class's declared fields and then make them accessible:

Field f = obj.getClass().getDeclaredField("stuffIWant"); //NoSuchFieldException
f.setAccessible(true);
Hashtable iWantThis = (Hashtable) f.get(obj); //IllegalAccessException

EDIT: as has been commented by aperkins, both accessing the field, setting it as accessible and retrieving the value can throw Exceptions, although the only checked exceptions you need to be mindful of are commented above.

The NoSuchFieldException would be thrown if you asked for a field by a name which did not correspond to a declared field.

obj.getClass().getDeclaredField("misspelled"); //will throw NoSuchFieldException

The IllegalAccessException would be thrown if the field was not accessible (for example, if it is private and has not been made accessible via missing out the f.setAccessible(true) line.

The RuntimeExceptions which may be thrown are either SecurityExceptions (if the JVM's SecurityManager will not allow you to change a field's accessibility), or IllegalArgumentExceptions, if you try and access the field on an object not of the field's class's type:

f.get("BOB"); //will throw IllegalArgumentException, as String is of the wrong type


Related Topics



Leave a reply



Submit