Java – NoSuchFieldException when using getDeclaredField() and field exists

javareflection

java.lang.NoSuchFieldException: c
at java.lang.Class.getDeclaredField(Unknown Source)
at ru.onlymc.OnlyMZ.CustomEntityType.getPrivateStatic(CustomEntityType.java:177)

Method:

private static Object getPrivateStatic(Class clazz, String f) throws Exception {
    Field field = clazz.getDeclaredField(f);
    field.setAccessible(true);
    return field.get(null);
}

Calling:

private static void a(Class paramClass, String paramString, int paramInt) {
    try {
        ((Map) getPrivateStatic(sg.class, "c")).put(paramString, paramClass);
        //...
    } catch (Exception exc) {
        exc.printStackTrace();
    }
}

sg.class (from decompile to sure about required fields really exists):

private static Map c = new HashMap();
private static Map d = new HashMap();
private static Map e = new HashMap();
private static Map f = new HashMap();
private static Map g = new HashMap();
public static HashMap a = new LinkedHashMap();

Best Solution

Sorry, I can't reproduce this one.

Here's the full source code that I ran:

import java.lang.reflect.*;
import java.util.*;

@SuppressWarnings("unchecked")
public class ReflectionTest {

    private static Object getPrivateStatic(Class clazz, String f) throws Exception {
        Field field = clazz.getDeclaredField(f);
        field.setAccessible(true);
        return field.get(null);
    }

    private static void a(Class paramClass, String paramString, int paramInt) {
        try {
            ((Map) getPrivateStatic(sg.class, "c")).put(paramString, paramClass);
            //...
        } catch (Exception exc) {
            exc.printStackTrace();
        }
    }

    public static void main(String[] args) throws Exception {
        a(String.class, "test", 0);
        sg.printC();
    }
}

class sg {
    private static Map c = new HashMap();
    private static Map d = new HashMap();
    private static Map e = new HashMap();
    private static Map f = new HashMap();
    private static Map g = new HashMap();
    public static HashMap a = new LinkedHashMap();

    public static void printC() {
        System.out.println(c);
    }
}

This was the output I got when I ran it:

{test=class java.lang.String}

Given that you haven't specified the full decompiled source of the sg class, I can only guess at a couple of things that may have happened:

  • There is more than one class named sg, your code is using one of them but your decompiled output comes from a different one.
  • The fields exist within an inner class inside sg.

EDIT: the class sg you linked to below appears to contain a static field c, and contains no inner class, so I would expect to be able to use reflection to access this field. I cannot use your sg class with the ReflectionTest class I wrote above because it depends on numerous other classes with obfuscated names such as xk.

I can only conclude that you have some confusion about exactly which class you are attempting to access the field c from. I suggest altering your getPrivateStatic method to the following, which may provide a more helpful error message, including the name of the class and all of the fields within it:

    private static Object getPrivateStatic(Class clazz, String f) throws Exception {
        try {
            Field field = clazz.getDeclaredField(f);
            field.setAccessible(true);
            return field.get(null);
        }
        catch (NoSuchFieldException e) {
            // Throw a more helpful exception.
            throw new NoSuchFieldException(
                "Could not find field named '" + f + "' in class '" + clazz +
                "'.  All fields: " + Arrays.asList(clazz.getDeclaredFields()));
        }
    }