javareflection

Java Reflection - Loading a field with dependency


I want to get the field names of a class through reflection, but one of the fields is from a class that is not in the jar file and was added with a dependency, and it throws NoClassDefFoundError exception.

Is there a way I can skip that field or load it without needing that dependency?

@Nullable
public Class<?> loadClass(String name) {
    try {
        return Class.forName(name, false, classLoader);
    } catch (ClassNotFoundException e) {
        LOGGER.error("Class {} is not loaded.", name);
        return null;
    }
}
Class<?> clazz = mcLoader.loadClass("className");
List<String> fieldNames = new ArrayList<>();
for (Field field: clazz.getDeclaredFields()) {
    field.setAccessible(true);
    fieldNames.add(field.getName() + ":" + field.getType().getName());
}

try-catch didn't help because the exception is coming from clazz.getDeclaredFields() and if I use try-catch, non of fields will load as the field with dependency is the first field.


Solution

  • I want to get the field names of a class through reflection

    If you don't already have the field names, then your alternatives for getting them by reflection are Class.getDeclaredFields() and Class.getFields(), depending on whether you want to include inherited fields.

    try-catch didn't help because the exception is coming from clazz.getDeclaredFields() and if I use try-catch, non of fields will load as the field with dependency is the first field.

    These methods will attempt to load any unloaded classes representing the fields' data types, and if they cannot do so then they will throw instead of returning a result. They return all the results at once, as an array, so there is no provision for selective or partial results, and a problem with any field will scuttle the whole thing.

    Overall, there's not much you can do with a Class object if you cannot load all the reflected class's dependencies. Only when lazy linking is performed can you even get your hands on such an object in the first place.

    Is there a way I can skip that field or load it without needing that dependency?

    Not with reflection. You could conceivably analyze the class file directly, without performing Java class loading at all, but that's a different thing. The Java standard library has no provision for it before Java 22, but there are third-party tools that might help. Java 24 has has added a classfile API (previewed starting in Java 22) that looks like it provides an alternative to reflection for what you describe [thanks @Slaw].