views:

150

answers:

3

My application consists of several JAR files. I would like to iterate over all of the JAR files and find all classes that subclass a particular class, so that I can cause their static initializers to run.

I looked though the Javadocs for java.lang.ClassLoader, but can't find any method that does this.

I am trying to implement the "Product Trader" pattern (http://www.ubilab.com/publications/print_versions/pdf/plop-96-producttrader.pdf), with the classes "self-registering" in the abstract superclass. The superclass will have a HashMap that maps the service a subclass provides and the java.lang.Class file that handles that service.

The problem is that a class does not run it's static initializers until it is loaded. If I can iterate all of the subclasses, I can force each to load and run it's initializers.

Thanks, Ralph

+5  A: 

This is not generally solvable. A ClassLoader is not required to be able to iterate over the Classes it could load. The easiest example of a ClassLoader that can't do that is when you load classes from a http:// base URL: HTTP provides no standardized way to enumerate the content of any given URL.

An better way to implement this is to use the ServiceLoader and let all implementing classes register themselves via a simple entry in their jar file.

Joachim Sauer
ServiceLoader seems to be pretty "heavy weight" for this use
Ralph
@Ralph: really? it seems like it's exactly what you want. No need to implement any registering yourself. Just ask the ServiceLoader for all implementations of the interface.
Joachim Sauer
I'll look more closely. Thanks. Now if I can get ANT to build the META-INF stuff automatically, it might be perfect.
Ralph
A: 

If you really need to do this the only real way is to iterate through the classpath, scanning the jars and directories for class files, loading that class and looking at it's parent class.

Note, some classes will have static initialising code that can have bad side affects, e.g. loading X11 classes from the runtime can hang for a long long time. If possible try to restrict what classes you load to specific packages, e.g. com.company (you can of course identify the package by the path of the class file relative to the root to the classpath item).

[Note the ServiceLoader suggested by Joachim Sauer, or a framework that provides a similar mechanism is a much better solution]

vickirk
A: 

This is obviously not solvable very simply.

However, there are solutions, like the one mentionned in this Javaworld article.

Generally speaking, it consists into exploration all elements from the CLASSPATH. if they're jar files, explore them looking for classes, load those classes and see if they extend you reference base class. However, i would strongly suggest you use a more "mature" mechanism like IoC or a plugin architecture.

I'm obviously thinking about JSPF, as an example.

Riduidel