Hi I've already worked with Reflection in Java. But if you are using the java standards (e.g. injecting a private field) you have to write a lot of code to get the job done.
What is the shortest way to inject a private field in a Java Object? Are there implementations in widely used and production ready libraries?
Without using external libraries you need to:
get the Field instance
set the field instance as accessible
set the new value
As follow:
Field f1 = obj.getClass().getDeclaredField("field");
f1.setAccessible(true);
f1.set(obj, "new Value");
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>
If you're using the Spring Framework, there is an utils class named ReflectionUtils
Here is a way to inject a value into a private field.
According to :
findField(Class<?> clazz, String name, Class<?> type)
and
setField(Field field, #Nullable Object target, #Nullable Object value)
You can write:
final Field field = ReflectionUtils.findField(Foo.class, "name", String.class)
ReflectionUtils.setField(field, targetObject, "theNewValue")
It is certainly not the shortest way to write this but it is shorter than the basic JDK tools to do this and I trusts people who are developing Spring so I am confident enough. Just be sure you actually really need reflection before doing this.
Plus if this is for a testing purpose, there is ReflectionTestUtils that provides you some methods too.
You'll find everything in the docs here
Hope it helps.
what I would do is make this a helper method.
public static void changeField(Class cc, String field, String newValue) throws NoSuchFieldException, IllegalAccessException {
Field f = cc.getDeclaredField(field);
f.setAccessible(true);
f.set(cc, newValue);
f.setAccessible(false);
}
and call it like the following
changeField(cc, "field", "newValue");
I am new to aspectJ. I would like to understand field read access and field write access pointcuts. Assume I have a private static string variable "name" in my class "Field".
private static String name;
I need to assign a value when name is read and throw exception when it is set.
Below is the aspectJ code.
package main.java.testaop.field;
public aspect FieldAspect {
pointcut getName() : get(private static String Field.name);
pointcut setName() : set(private static String Field.name);
before() : getName() {
"john";}
before() : setName() {
throw new Exception(); }
I am getting errors when compiling. I knew this is wrong. Can anyone help to make me understand how this works.
You want to access private fields (which is possible, but a smell conceptually). In order to do that declare your aspect as privileged:
public privileged aspect FieldAspect { ... }
Is there any way to get a Field reference from an instance (not from a class) ?
This is an example :
public class Element {
#MyAnnotation("hello")
public String label1;
#MyAnnotation("world")
public String label2;
}
public class App {
private Element elem = new Element();
public void printAnnotations() {
String elemLabel1 = elem1.label;
String elemLabel2 = elem2.label;
// cannot do elemLabel.getField().getDeclaredAnnotations();
String elemLabel1AnnotationValue = // how ?
String elemLabel2AnnotationValue = // how ?
}
}
Sorry for not being too clear, but i already know how to fetch Fields from a class (Class --> Field --> DeclaredAnnotations)
What i am wondering is how to get the Field for a particular instance.
In this example, from elemLabel1 string instance, i wish to be able to get the Field of Element.label1.
What exactly do you mean? A Field on defined on the Class. You can get the value for a specific instance:-
private static class Test {
private int test = 10;
}
public static void main(String[] args) throws Exception {
final Test test = new Test();
final Field field = Test.class.getDeclaredField("test");
field.setAccessible(true);
final int value = field.getInt(test);
System.out.println(value);
}
The the class Test has a Field called test. This is true of any Test - it is defined in the Class. The instance of the class is has a specific value for that Field, in this case 10. This can retrieved for a specific instance using the getXXX or get method.
EDIT
From the code in your question it looks like you want the value of an Annotation field not the value of a class field.
In Java, values in annotations are compile time constants and therefore are also defined at the class rather than instance level.
public class Element {
#MyAnnotation("l")
public String label;
}
In your example, the MyAnnotation value field must be equal to 1 for every instance of Element.
Field belongs to class. Therefore you actually want to do the following:
elemLabel.getClass().getField("theFieldName").getDeclaredAnnotations();
However although your field is public typically all fields should be private. In this case use getDeclaredField() instead of getField().
EDIT
you have to call field.setAccessible(true) before using the field.
How can I set or get a field in a class whose name is dynamic and stored in a string variable?
public class Test {
public String a1;
public String a2;
public Test(String key) {
this.key = 'found'; <--- error
}
}
You have to use reflection:
Use Class.getField() to get a Field reference. If it's not public you'll need to call Class.getDeclaredField() instead
Use AccessibleObject.setAccessible to gain access to the field if it's not public
Use Field.set() to set the value, or one of the similarly-named methods if it's a primitive
Here's an example which deals with the simple case of a public field. A nicer alternative would be to use properties, if possible.
import java.lang.reflect.Field;
class DataObject
{
// I don't like public fields; this is *solely*
// to make it easier to demonstrate
public String foo;
}
public class Test
{
public static void main(String[] args)
// Declaring that a method throws Exception is
// likewise usually a bad idea; consider the
// various failure cases carefully
throws Exception
{
Field field = DataObject.class.getField("foo");
DataObject o = new DataObject();
field.set(o, "new value");
System.out.println(o.foo);
}
}
Class<?> actualClass=actual.getClass();
Field f=actualClass.getDeclaredField("name");
The above code would suffice .
object.class.getField("foo");
Unfortunately the above code didn't work for me , since the class had empty field array.
I have a poorly designed class in a 3rd-party JAR and I need to access one of its private fields. For example,
why should I need to choose private field is it necessary?
class IWasDesignedPoorly {
private Hashtable stuffIWant;
}
IWasDesignedPoorly obj = ...;
How can I use reflection to get the value of stuffIWant?
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
Try FieldUtils from Apache commons-lang3:
FieldUtils.readField(object, fieldName, true);
P.S. In my opinion, reflection is evil.
Reflection isn't the only way to resolve your issue (which is to access the private functionality/behaviour of a class/component)
An alternative solution is to extract the class from the .jar, decompile it using (say) Jode or Jad, change the field (or add an accessor), and recompile it against the original .jar. Then put the new .class ahead of the .jar in the classpath, or reinsert it in the .jar. (the jar utility allows you to extract and reinsert to an existing .jar)
As noted below, this resolves the wider issue of accessing/changing private state rather than simply accessing/changing a field.
This requires the .jar not to be signed, of course.
One other option that hasn't been mentioned yet: use Groovy. Groovy allows you to access private instance variables as a side effect of the design of the language. Whether or not you have a getter for the field, you can just use
def obj = new IWasDesignedPoorly()
def hashTable = obj.getStuffIWant()
Using the Reflection in Java you can access all the private/public fields and methods of one class to another .But as per the Oracle documentation in the section drawbacks they recommended that :
"Since reflection allows code to perform operations that would be illegal in non-reflective code, such as accessing private fields and methods, the use of reflection can result in unexpected side-effects, which may render code dysfunctional and may destroy portability. Reflective code breaks abstractions and therefore may change behavior with upgrades of the platform"
here is following code snapts to demonstrate basic concepts of Reflection
Reflection1.java
public class Reflection1{
private int i = 10;
public void methoda()
{
System.out.println("method1");
}
public void methodb()
{
System.out.println("method2");
}
public void methodc()
{
System.out.println("method3");
}
}
Reflection2.java
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class Reflection2{
public static void main(String ar[]) throws IllegalAccessException, IllegalArgumentException, InvocationTargetException
{
Method[] mthd = Reflection1.class.getMethods(); // for axis the methods
Field[] fld = Reflection1.class.getDeclaredFields(); // for axis the fields
// Loop for get all the methods in class
for(Method mthd1:mthd)
{
System.out.println("method :"+mthd1.getName());
System.out.println("parametes :"+mthd1.getReturnType());
}
// Loop for get all the Field in class
for(Field fld1:fld)
{
fld1.setAccessible(true);
System.out.println("field :"+fld1.getName());
System.out.println("type :"+fld1.getType());
System.out.println("value :"+fld1.getInt(new Reflaction1()));
}
}
}
Hope it will help.
As oxbow_lakes mentions, you can use reflection to get around the access restrictions (assuming your SecurityManager will let you).
That said, if this class is so badly designed that it makes you resort to such hackery, maybe you should look for an alternative. Sure this little hack might be saving you a few hours now, but how much will it cost you down the road?
Java 9 introduced Variable Handles. You can access a private field of a class using them.
The code for your example will look like following:
var lookup = MethodHandles.lookup();
var handle = MethodHandles
.privateLookupIn(IWasDesignedPoorly.class, lookup)
.findVarHandle(IWasDesignedPoorly.class, "stuffIWant", Hashtable.class);
var value = handle.get(obj);
It is also advisable to use Lookup and VarHandle objects as static final fields.
Use the Soot Java Optimization framework to directly modify the bytecode.
http://www.sable.mcgill.ca/soot/
Soot is completely written in Java and works with new Java versions.
If using Spring:
In a testing context, ReflectionTestUtils provides some handy tools that can help out here with minimal effort. It's described as being "for use in unit and integration testing scenarios".
In a non-testing context, there is also a similar class named ReflectionUtils but this is described as "Only intended for internal use" - see this answer for a good interpretation of what this means.
To address the example in the original post:
Hashtable iWantThis = (Hashtable)ReflectionTestUtils.getField(obj, "stuffIWant");
You need to do the following:
private static Field getField(Class<?> cls, String fieldName) {
for (Class<?> c = cls; c != null; c = c.getSuperclass()) {
try {
final Field field = c.getDeclaredField(fieldName);
field.setAccessible(true);
return field;
} catch (final NoSuchFieldException e) {
// Try parent
} catch (Exception e) {
throw new IllegalArgumentException(
"Cannot access field " + cls.getName() + "." + fieldName, e);
}
}
throw new IllegalArgumentException(
"Cannot find field " + cls.getName() + "." + fieldName);
}
You can use jOOR for that.
class Foo {
private final String value = "ABC";
}
class Bar {
private final Foo foo = new Foo();
public String value() {
return org.joor.Reflect
.on(this.foo)
.field("value")
.get();
}
}
class BarTest {
#Test
void accessPrivateField() {
Assertions.assertEquals(new Bar().value(), "ABC");
}
}
Just an additional note about reflection: I have observed in some special cases, when several classes with the same name exist in different packages, that reflection as used in the top answer may fail to pick the correct class from the object. So if you know what is the package.class of the object, then it's better to access its private field values as follows:
org.deeplearning4j.nn.layers.BaseOutputLayer ll = (org.deeplearning4j.nn.layers.BaseOutputLayer) model.getLayer(0);
Field f = Class.forName("org.deeplearning4j.nn.layers.BaseOutputLayer").getDeclaredField("solver");
f.setAccessible(true);
Solver s = (Solver) f.get(ll);
(This is the example class that was not working for me)
It is quite easy with the tool XrayInterface. Just define the missing getters/setters, e.g.
interface BetterDesigned {
Hashtable getStuffIWant(); //is mapped by convention to stuffIWant
}
and xray your poor designed project:
IWasDesignedPoorly obj = new IWasDesignedPoorly();
BetterDesigned better = ...;
System.out.println(better.getStuffIWant());
Internally this relies on reflection.
Try to go around the problem for the case, the calass of which you want to set/get data is one of your own classes.
Just create a public setter(Field f, Object value) and public Object getter(Field f) for that. You can even do some securoty check on your own inside theses member functions. E.g. for the setter:
class myClassName {
private String aString;
public set(Field field, Object value) {
// (A) do some checkings here for security
// (B) set the value
field.set(this, value);
}
}
Of course, now you have to find out the java.lang.reflect.Field for sString prior to setting of field value.
I do use this technique in a generic ResultSet-to-and-from-model-mapper.