简体   繁体   中英

Using reflection get a static private hashmap in java

I'm trying to find a way to extract a HashMap from a private static field within another class via Java.

eg.

Inside FooClass there is a static field that looks like this:

private Map entityRenderMap;

Then in its construct it has:

entityRenderMap = new HashMap();

How do you get the values within entityRenderMap via Reflection in Java? I've tried this but get errors:

cl = RenderManager.class.getDeclaredField("entityRenderMap");
        cl.setAccessible(true);
        Object foo = cl.get(this.entityRenderMap);
        Mod.log(cl.getName());

The error I get is:

java.lang.IllegalArgumentException: Can not set java.util.Map field RenderManager.entityRenderMap to java.util.HashMap
at sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(Unknown Source)
at sun.reflect.UnsafeFieldAccessorImpl.throwSetIllegalArgumentException(Unknown Source)
at sun.reflect.UnsafeFieldAccessorImpl.ensureObj(Unknown Source)
at sun.reflect.UnsafeObjectFieldAccessorImpl.get(Unknown Source

Are you certain it is a static field. The javadoc of the get method clearly states:

If the underlying field is a static field, the obj argument is ignored; it may be null.

Otherwise, the underlying field is an instance field. If the specified obj argument is null, the method throws a NullPointerException. If the specified object is not an instance of the class or interface declaring the underlying field, the method throws an IllegalArgumentException.

So with a static field you would not get the IllegalArgumentException since the parameter is ignored. Further, the code you posted shows it is not a static field but a regular field (since it lacks the word static , and its initialized in the constructor).

If you want to access the field of a certain instance A , you should pass that instance A to the Field#get method, and not the A.field as you are trying to do with your cl.get(this.entityRenderMap) call.

You can take a look at this tutorial for some examples

If the field is really static, you should pass null as an argument to cl.get() .

If the field is not static, then you must pass the instance of FooClass which you want to get the field value from:

FooClass fc = new FooClass(); // or whatever, provided that fc is a FooClass instance
Object foo = cl.get(fc);

First, your code doesn't match your explanation. Is it really a static field or is it not (your code says it's not)?

If it is static, you should pass null as argument to cl.get() (you don't need an instance to access static members).

However, I suspect that your field is actually not static, and your passing the wrong instance to cl.get() . The JavaDocs to Field.get() state it would throw an IllegalArgumentException in this case. You need to pass a RenderManager instance to this method. Your code looks like your passing a Map (the entityRenderMap ).

And last, is this code inside your RenderManager class? I suspect this, because your accessing a field with this with the same name as the field you want to set. In this case, don't use reflection at all!

I'm assuming cl is a java.lang.reflect.Field . The documentation states that Fields' get-method will throw:

IllegalArgumentException - if the specified object is not an instance of the class or interface declaring the underlying field (or a subclass or implementor thereof).

You should be passing the RenderManager -object to the get-method instead of the field (unless it's static, which it is not according to your example).

vim Test.java
    import java.util.*;
    import com.dp4j.*;

class FooClass{

private static Map entityRenderMap;

FooClass(){
entityRenderMap = new HashMap();
}

}

public class Test{
@Reflect
public static void main(String... args){

Map reflectEntityMap = FooClass.entityRenderMap;
}
}


javac -cp ~/ws/dp4j/dp4j.jar -Averbose=true Test.java
Test.java:16: Note: 
import java.util.*;
import com.dp4j.*;

class FooClass {
    private static Map entityRenderMap;

    FooClass() {
        entityRenderMap = new HashMap();
    }
}
public class Test {

    public Test() {
        super();
    }

    @Reflect()
    public static void main(String... args) throws java.lang.ClassNotFoundException, java.lang.NoSuchFieldException, java.lang.IllegalArgumentException, java.lang.IllegalAccessException {
        java.lang.reflect.Field entityRenderMapField = null;
        entityRenderMapField = Class.forName("FooClass").getDeclaredField("entityRenderMap");
        entityRenderMapField.setAccessible(true);
        Map reflectEntityMap;
        reflectEntityMap = (.java.util.Map)entityRenderMapField.get("");
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM