Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java reflection question

I am working on a project that uses reflection to get the fields of a running java application.

I managed to get the fields, but I can not read or write to them. This is an example I found on the web:

Class aClass = MyObject.class
Field field = aClass.getField("someField");
MyObject objectInstance = new MyObject();
Object value = field.get(objectInstance);
field.set(objetInstance, value);

The problem is that I use classes from a running jar file, and the classes I try to manipulate are obtained from the classLoader. So instead of 'MyObject.class' I just have the '.class'. To get the 'MyObject' I tried to use a ClassLoader but that did not work.

If I just use '.class':

Object value = field.get(theLoadedClass);

I will get this error:

java.lang.IllegalArgumentException: Can not set int field myClass.field to java.lang.Class

Thanks.

like image 622
Natan Griefwell Avatar asked Jul 12 '11 07:07

Natan Griefwell


3 Answers

This should help:

Class aClass = myClassLoader.loadClass("MyObject"); // use your class loader and fully qualified class name
Field field = aClass.getField("someField");
// you can not use "MyObject objectInstance = new MyObject()" since its class would be loaded by a different classloader to the one used to obtain "aClass"
// instead, use "newInstance()" method of the class
Object objectInstance = aClass.newInstance();
Object value = field.get(objectInstance);
field.set(objetInstance, value);
like image 189
JB- Avatar answered Oct 04 '22 16:10

JB-


You need an instance of the appropriate class to pass into the field.get/set methods.

To get an instance from a class you can try these options:

Class<?> clazz = MyObject.class;
// How to call the default constructor from the class:
MyObject myObject1 = clazz.newInstance(); 
// Example of calling a custom constructor from the class:
MyObject myObject2 = clazz.getConstructor(String.class, Integer.class).newInstance("foo", 1); 
like image 26
Bohemian Avatar answered Oct 04 '22 15:10

Bohemian


From the documentation: java.lang.IllegalArgumentException is thrown:

If, after possible unwrapping, the new value cannot be converted to the type of the underlying field by an identity or widening conversion, the method throws an IllegalArgumentException.

This means the object type (Object) you attempt to set the field to cannot be converted to the actual type. Try not using an Object there.

Unrelated, looking at your code I would change the

Class aClass = MyObject.class; 

piece to:

Class aClass = Class.forName("fullyQualifiedMyObjectClassName.e.g.com.bla.bla.MyObject");
like image 37
Nikola Yovchev Avatar answered Oct 04 '22 14:10

Nikola Yovchev