Take the 2-minute tour ×

I am working on a command line app that loads user specified text translators at runtime (path to class files/jar provided via command line arg). Basically I am taking that argument and using it to create a URLClassLoader. Then I need to find all classes available to the URLClassloader that implement the Transable interface.

Right now I am only allowing this command line arg to be a directory with class files in it. Making the solution fairly simple (code below). But honestly I don't like the solution as it breaks down for jar files, directory of jar files, etc... Also, this obviously breaks down for any classes with a defined package, as loadClass needs the full name including the package. Anyone have a better method?

    File d = new File(path);
    if(d.isDirectory()) {
        URL url = d.toURI().toURL();
        ClassLoader cl = new URLClassLoader(new URL[]{url});

        FilenameFilter filter = new FilenameFilter() {
            public boolean accept(File dir, String name) {
                return name.endsWith(".class");

        for(File f : d.listFiles(filter)) {
            String name = f.getName().substring(0, f.getName().indexOf("."));
            String key = "";
            if(name.endsWith("Translator")) {
                key = name.substring(0, name.indexOf("Translator"));
            else if(name.endsWith("translator")) {
                key = name.substring(0, name.indexOf("translator"));
                key = name;

            Class c = cl.loadClass(name);
            if(Transable.class.isAssignableFrom(c)) {
                Transable t = (Transable)c.newInstance();
                env.registerTranslator(key, t);
            else {
                System.out.println("[ClassLoader] "+c.getCanonicalName()+" will not be loaded. It is not a translator class");
    else {
        throw new Error("NOT IMPLEMENTED");
share|improve this question
just go in the jar file and check all entries. –  irreputable Feb 17 '11 at 0:32

5 Answers 5

up vote 3 down vote accepted

You may just have to brute force it if you continue down this road. To my knowledge the default class loader will not even load a class into the JVM unless it is referenced somehow. Which means, some of your classes will be basically invisible unless you know their fully qualified class name to load them.

You may want to reconsider your requirements. As it would be far easier to load a set of Translators that you have been given the class names for.

share|improve this answer
I am considering moving some of this off to a config file that would require explicit names, or at least the name of the package containing the translator classes. Its a better approach, I just want to make sure the the other option can't be implemented cleanly first. –  jdc0589 Feb 17 '11 at 0:14
@jdc0589 There are solutions for jars and local files, but AFAIK not a generic one for any kind of classloader. –  biziclop Feb 17 '11 at 0:18
care to elaborate? I am only concerned with local files and local jars –  jdc0589 Feb 17 '11 at 3:45
Changed the format of my input files to require explicit definition of translator classes. Definitely the best option. –  jdc0589 Feb 26 '11 at 1:24

This may fit the bill. If not, you ought to be able to look through their source to get an idea of what will work for you. http://code.google.com/p/reflections/

share|improve this answer
Looks really interesting..but can you say dependency HELL? –  jdc0589 Feb 17 '11 at 0:42
I just saw a reference to it earlier in the day and then stumbled on your question so thought I would pass it along. I've never used it, but thought if nothing else, you could look through the source and see what they are doing. –  digitaljoel Feb 17 '11 at 16:00

Would this help?

Since Class c = cl.loadClass(name);

Class method getInterfaces() returns an array of classes

Check each class name for match to translator class name.

share|improve this answer
That is not really the issue. Thanks though –  jdc0589 Feb 17 '11 at 0:42

In principle this can't work for arbitrary classloaders, as they may use any way imaginable to actually load the classes, and not have any "directory listening" function at all.

A classloader might even generate classes (i.e. the bytecode for the classes) on the fly whenever a loadClass comes, and imagine a TransableClassloader where each such automatically defined class would implement your interface - your program would never end.

That said, for an URLClassloader you can use getURLs(), and for the jar: and file: URL you can use the JarFile or File api to get the list of filenames (and thus Classnames) to try. As you have the root of your package hierarchy given in the URL, finding the right package name is not difficult, too.

(If you need more details, say it.)

Edit: For the package names, they correspond to the directory names inside of your hierarchy. So, when you have a base URL which corresponds to (say) dir/classes, and find a class-file named dir/classes/com/company/gui/SimpleTranslator.class, it corresponds to class com.company.gui.SimpleTranslator.

So, remove the base prefix and replace / by . (and cut of the .class). (In a JarFile you don't have to cut a prefix off.)

Actually, if you use a recursive method to traverse your File hierarchy, you can build up your package-name with the same method, simply by appending Strings (give them as a parameter to the next recursive Invocation):

public void searchClassesInDir(File dir, String packagePrefix) {
    if(dir.isDirectory()) {
        String prefix = packagePrefix + dir.getName() + ".";
        for(File f : dir.listFiles()) {
            searchClasses(f, prefix);
    else {
       String fileName = dir.getName();
       if(! fileName.endsWith(".class"))
       String className = packagePrefix + fileName.substring(0, fileName.length()-".class".length());
       // now do the rest of your processing

searchClasses(new File(url.toURI()), "");
share|improve this answer
I think this is the path I will take. I know how to do everything aside from determining package names. The only method I can think of is to just get the path of the class entry in the jar file, replace the file separators with a '.' and chop the '.class' off the end. There another way? –  jdc0589 Feb 17 '11 at 0:59
I added an example here. But chopping off the '.class' and converting '/' to '.' works too. –  Paŭlo Ebermann Feb 17 '11 at 1:16
You can also add your filter to the listFiles() call, but make sure it catches subdirectories, too (or in a second loop). For a jar file this works similar, I think, you just need to traverse the JarEntrys (and don't need recursion, instead the replacement). –  Paŭlo Ebermann Feb 17 '11 at 1:21

Instead of trying to search for these yourself, you should instead take a look at using Java's Service Provider Interface (SPI) and the newly public (as of Java 6) ServiceLoader class. SPI is a pretty much a standard way to do what you are describing in Java.

This article does a nice job summing up how to use SPI, and also discusses how to use it for runtime discovery of new implementation providers.

share|improve this answer
Sounds awesome, will take a look asap. Thanks –  jdc0589 Feb 17 '11 at 2:59
A little confused here. Maybe I just havent found it yet..but it seems like this only returns the default implementations defined in my META-INF/services/org.jextend.Transable file? At least thats all I can get it to do now, even though I constructed the ServiceLoader with class loader argument that has access to other implementations. –  jdc0589 Feb 17 '11 at 3:35
Found this text in the link you posted:"Also, the current ServiceLoader class can't tell your application when new providers are available at runtime." Whats the deal? –  jdc0589 Feb 17 '11 at 3:42
There could be multiple META-INF/services/org.jextend.Transable files in different root directories or jar files found by your classloader(s). There is also a tool to help you create those files during build: code.google.com/p/spi/wiki/GettingStarted –  hd42 Feb 17 '11 at 6:34
The deal with not discovering new providers during runtime is that the ServiceLoader will look for and parse the service description files during startup, so when you put a new file and service implementation class in your classpath while your program is running, it won't be picked up right away but only after you restart your program. –  hd42 Feb 17 '11 at 6:37

Your Answer


