4

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();
Rizier123
  • 58,877
  • 16
  • 101
  • 156
Fullstack
  • 135
  • 1
  • 1
  • 11
  • You cannot get static fields with getDEclaredField, it is not entirely clear why. There have been questions on this before. – eckes Feb 15 '15 at 03:01
  • possible duplicate of [Change private static final field using Java reflection](http://stackoverflow.com/questions/3301635/change-private-static-final-field-using-java-reflection) – eckes Feb 15 '15 at 03:01

2 Answers2

1

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()));
        }
    }
Luke Woodward
  • 63,336
  • 16
  • 89
  • 104
0

You are trying to get the field of the object null. See documentation on Field.get(Object)

You need to provide an object to get its field content. Or you need to provide a class to get a static fields content.

So you should write the following:

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

btw. It is not considered good programming style to use reflection in production code since it e.g. makes refactoring problematic.

If you still need to use reflection (or are not working on production-code), use a framework for this kind of stuff (accessing private static field). With e.g. PrivilegedAccessor this method would be a 1-liner:

PA.getValue(clazz, f);
Sebastian
  • 877
  • 1
  • 9
  • 20
  • From the documentation page linked to: 'If the underlying field is a static field, the obj argument is ignored; it may be null. '. The problem here is most definitely not the line `field.get(null)`. – Luke Woodward Feb 14 '15 at 17:22