I've looked through every entry related to Java reflection I can find and none seem to address the situation I'm dealing with. I have a class A with a static nested class in it, B. Class A also has as one of its fields, an array of type B, called bArray. I need to access this field from outside the class as well as the private members of the elements of bArray. I have been able to get the static nested class using getDeclaredClasses and I would normally get the private field bArray with getDeclaredFields and setAccessible but I can't seem to put it all together to be able to iterate through bArray from outside the class.
Here is an example class structure that I'm working with.
public class A {
private A.B[] bArray = new A.B[16];
private static class B {
private int theX;
private int theY;
B(int x, int y) {
this.theX = x;
this.theY = y;
}
// More methods of A.B not included
}
}
I ultimately need to get at bArray and its fields theX and theY from outside of class A.
I cannot use the names of the classes like Class.forName("classname") because the code all gets run through an obfuscator and the names all change except the ones in strings of course. I can use the field order (index) but not the name due to obfuscation. I've managed to pick out all of the fields, methods and whatnot that I need except this private static nested array field.
This is the direction I've tried. The first 3 lines of this seem to do what I want but the 4th says ABArray cannot be resolved:
A myA = new A();
Class AB = stealNamedInnerClass(A.class);
Class ABArray = Array.newInstance(AB, 0).getClass();
ABArray myABArray = (ABArray)stealAndGetField(myA, ABArray);
These are the utility functions I'm referencing:
public static Field stealField(Class typeOfClass, Class typeOfField)
{
Field[] fields = typeOfClass.getDeclaredFields();
for (Field f : fields) {
if (f.getType().equals(typeOfField)) {
try {
f.setAccessible(true);
return f;
} catch (Exception e) {
break; // Throw the Exception
}
}
}
throw new RuntimeException("Couldn't steal Field of type \"" + typeOfField + "\" from class \"" + typeOfClass + "\" !");
}
public static Object stealAndGetField(Object object, Class typeOfField)
{
Class typeOfObject;
if (object instanceof Class) { // User asked for static field:
typeOfObject = (Class)object;
object = null;
} else {
typeOfObject = object.getClass();
}
try {
Field f = stealField(typeOfObject, typeOfField);
return f.get(object);
} catch (Exception e) {
throw new RuntimeException("Couldn't get Field of type \"" + typeOfField + "\" from object \"" + object + "\" !");
}
}
public static Class stealNamedInnerClass(Class clazz)
{
Class innerClazz = null;
Class[] innerClazzes = clazz.getDeclaredClasses();
if (innerClazzes != null) {
for (Class inner : innerClazzes) {
if (!inner.isAnonymousClass())
return inner;
}
}
return null;
}