ronif
ronif

Reputation: 805

Getting the path to a .class file of a dynamically loaded Class in JAVA

I'm looking to instantiate and map all classes in my class path of a given type.

I've done the scan using the Reflections library, and got a list of classes that were loaded.

Then, when I'm mapping them, I'm checking for conflicts (the key is the simple class name).

When that happens I would like to throw an exception, pointing out the fully qualified name of the conflicting classes, as well as the path they were loaded from (for instance in which JARs one might find each).

I realize one may load a class from memory as well, but assuming I was loading it from a JAR on disk, I wonder if there's any way of getting that path...

See code snippet below:

if (isConflictingFactoryRegistered(key, myFactory)) {
        Class<? extends MyFactory> class1 = factoryMap.get(key).getClass();
        Class<? extends MyFactory> class2 = myFactory.getClass();
        try {
            throw new RuntimeException("Found two conflicting factories for " + key
                    + ": 1. " + class1 + " in " + getClass().getResource(class1.getSimpleName()+".class").toURI() +
                       " 2. " + class2 + " in " + getClass().getResource(class2.getSimpleName()+".class").toURI());
        } catch (URISyntaxException e) {
            throw new RuntimeException(e);
        }
    } else {
        factoryMap.put(myFactory.getName(), myFactory);
    }

This code does compile - but it won't work; getClass().getResource(class1.getSimpleName()+".class") returns null. How can I get the path to the .class ?

Upvotes: 1

Views: 1770

Answers (1)

J Richard Snape
J Richard Snape

Reputation: 20344

I suggest you replace

throw new RuntimeException("Found two conflicting factories for " + key
  + ": 1. " + class1 + " in " + getClass().getResource(class1.getSimpleName()+".class").toURI() +
  " 2. " + class2 + " in " + getClass().getResource(class2.getSimpleName()+".class").toURI());

with

throw new RuntimeException("Found two conflicting factories for " + key
  + ": 1. " + class1 + " in " + class1.getResource(class1.getSimpleName()+".class").toURI() + 
 " 2. " + class2 + " in " + class2.getResource(class2.getSimpleName()+".class").toURI());

This works for two arbitrary classes on my machine.

In general, I think that Class.getResource() can only find resources available to the same ClassLoader that loaded that specific class - as per the API,

This method delegates to this object's class loader. If this object was loaded by the bootstrap class loader, the method delegates to ClassLoader.getSystemResource(java.lang.String).

I suspect that if you look at getClass().getClassLoader() and class1.getClassLoader() in your example, you may find that they are different.

Upvotes: 1

Related Questions