Is it possible to find all the implementors of an interface? That is, all sublclasses - not instances. After a thorough run through of the Reflection API and the classes Class, ClassLoader, and Package I'm inclined to say this isn't possible.

Can I inject my own classloader in somewhere? The desired functionality is this: You add your class to the classpath, and I know automatically at runtime.

Thanks!

[size=1]edit - added that the goal is subclasses, not instances[/size]

It is only possible in the sense that you will need to scan every class and test if it implements the interface.. This is one way of dealing with plugins for instance. But the search is limited to a specific folder or package. Maybe that is good enough for you.

Is it possible to find all the implementors of an interface? That is, all sublclasses - not instances. After a thorough run through of the Reflection API and the classes Class, ClassLoader, and Package I'm inclined to say this isn't possible.

Replace the main system classloader. There's several things that could be considered to be the "main system" classloader, but it's fairly obvious which the important one is when you look at the ClassLoader class API docs.

There are several articles on the net (I recall at least one on the JDC) that explain fun tricks to do with classloaders, and interposing your own classloader(s). The API docs (just had a quick look) explain how you can do it using a system property, but there are other ways too (just make sure you load your classloader before you reference any classes, IIRC).

There are static analysis tools that will do this for a codebase. At ru-time yeah you need to implement your own sub-class of ClassLoader (I suggest sub of URLClassLoader actually) that wil let you peek at whats been loaded/cached.

Realize though that any analysis only gives you the answer for oen state. Since classes are loadable dynamically, and under certai ncondistions ar even unloadable (collectable really), there is no one answer that is gauranteed correct for the entire run of the program.

Got a question about Java and game programming? Just new to the Java Game Development Community? Try my FAQ. Its likely you'll learn something!

I see now that we've put the cart before the horse. I found some code to change the system Classloader, but then I realized that for the ClassLoader approach to work my codebase would have to already know the name of the subclass in order for it to be loaded.

Now I'm thinking that I should analyze java.class.path and run through all the directories and jars, force eveything to load, and use instanceof. Can't wait to see how slow this is!

I see now that we've put the cart before the horse. I found some code to change the system Classloader, but then I realized that for the ClassLoader approach to work my codebase would have to already know the name of the subclass in order for it to be loaded.

You've lost me now; I have no idea why you would need to already know the name of each of the subclasses?. Perhaps you should explain what it is you're trying to achieve, rather than just ask about one low-level feature you're not sure about how/why to use (...in java; i.e. what you're familiar with from other environments seems to be sufficiently dissimilar to "the java way" for this particular situation as to be non helpful...).

You want to scan the jars and directories on the classpath (or a subset of it) and then peek at the files ending with .class using your classloader.In otherwords if they aren't loaded yet - load them. Hopefully they don't have to stay loaded.. I haven't actually done this before.

It sounds like you are trying to do what the Plugin code in JInput does, which is find all the installed implementors oif a given interface.

JInput does it the easy way. It uses a naming convention (*Plugin.class) to identify likely candidates, loads and instances them, and then uses reflection to make sure they really are plug-ins (implementors of the Plugin interface,)

This code is all available as part of JUtils.

If you dont want to use a naming convention and instance though you are going to have to dig into the VM spec and figure out how to read the inheritance data out of a raw .class file.

Nasty.

Got a question about Java and game programming? Just new to the Java Game Development Community? Try my FAQ. Its likely you'll learn something!

If I don't know the name of your class, I can't reference it in my code. If I reference your class, I already know what type it is.

Sorry, I wrongly assumed the classes would get referenced by someone else's code. You can reference one class belonging to someone else and end up loading many classes, none of which you have any idea existed (this is all done automatically).

If your use-case is "people give me class files; I load them without any further involvement of the author(s)", then I now understand OK. As Jeff has pointed out, the standard approach is to have a directory where the classes will be found and/or use a filename-prefix (the file-naming scheme is not mandatory to make this succeed).

Unfortunately, the design (flawed, IMHO, although most people disagree ) of java classloaders means that ".isInstance(...)" will *always* return false for a class loaded by a different classloader. So, when you're trying to check which are instances and which aren't, the object you use for comparison must be created with the same classloader as is loading these external classes; this sometimes bites people who wonder why none of the imported classes seem to be accepted by their classloader...

A naming convention sounds like a great compromise! Then I could scan all directories and jar files, but only load and check instanceof with the ideal subset. First, I think I'll check out JUtils though ...

Unfortunately, the design (flawed, IMHO, although most people disagree ) of java classloaders means that ".isInstance(...)" will *always* return false for a class loaded by a different classloader.

This "flaw" is vital to the operation of many more sophisticated Java systems such as RMI and Jini. Without name-space separation it becomes virtually impossible to do either code-mobility or code-container infra-structures.

The key is to understand that a ClassLoader does more then load classes. It is the public face of a class namespace and is well-isolated from other such namespaces. Class "foo" loaded nby classloader 1 IS a different class then class "foo" loaded by classloader 2 even if they are loaded from the same classfile.

This allows such things as static variables to operate as expected in the face of multiple apps running in the same VM and based on the same source.

Got a question about Java and game programming? Just new to the Java Game Development Community? Try my FAQ. Its likely you'll learn something!

So, when you're trying to check which are instances and which aren't, the object you use for comparison must be created with the same classloader as is loading these external classes;

Actually this isn't exactly true. Look at JUtils. The trick here is that class loaders chain and they defer to their parents first, so if a parent has loaded a class that is the class you will get. The simplest way to handle this is to have the Interface you are checking for either in the bootclasspath or the classpath. These loaders by definition MUST be at the beginning of a loader chain.

Got a question about Java and game programming? Just new to the Java Game Development Community? Try my FAQ. Its likely you'll learn something!

This "flaw" is vital to the operation of many more sophisticated Java systems such as RMI and Jini. Without name-space separation it becomes virtually impossible to do either code-mobility or code-container infra-structures.

Doesn't mean it has to be mandatory; it could be optional (theoretically - I'm not claiming it would have been easy to integrate with the other requirements of the original spec).

Given how many java programmers don't use RMI nor Jini (although probably many more should use the latter, and many fewer should use the former), but do use isInstance(), I think it's fair enough to say this part of the design could have been done better. I'm not claiming the current behaviour isn't valuable, just that IMHO it would be more intuitive NOT to be the default.

Quote

The key is to understand that a ClassLoader does more then load classes.

I agree entirely, and this is a large part of why I consider the current design "flawed". Since it does "much more than load classes" it should NOT be named "ClassLoader".

IMHO, a better API design would start from the concept of splitting the namespace-management, the class-loading, and the class-management (i.e. for stuff like type comparisons) into two, or possibly three, separate classes / sets of classes. I suspect that "hierarchy" namespace-management and "class" namespace management are two separate things, hence the need for three rather than two classes. The former deals with sandboxing, and separating differently-sourced class hierarchies; the latter is sort-of aspect-oriented, and cuts across sandboxes. Using both in conjunction, abstracted into separate classes, could give you all the benefits of both.

This could lead to a worse design, of course; as a systems architect, I don't feel that's a reason not to try . I live in hope that the ClassLoader's etc will get a "refresh" in some future release of java...

Quote

Actually this isn't exactly true.

Yes, sorry, I wasn't as precise as I could have been . The important point, of course, is the gotcha, and there's more than one way to skin the cat .

And the things they make possible IMO are well worth the learning curve.

Definitely agree here

Quote

But I can't think of another way to accomplish what they accomplish is cleanly and uncomplicatedly as they do.

Good API design is very hard, yes. Since it's my specialism, I'm more demanding than most . There are many bits of java that are excellent, but I get frustrated when the quality of API's (and/or documentation - e.g Swing has both some really really good docs, e.g. a 4 page class-comment IIRC, and some really terrible ones, e.g. some classes with no comments at all!) has very large variance.

Not exactly a timely post, but here is code to find all subclasses of a class (or all implementors of an interface) on your classpath.

To use it, add these classes to your classpath and from somewhere in your program call: Class[] interestingClasses = Subclasses.of( MyInterface.class );// or add a regexClass[] interestingClasses = Subclasses.of( MyClass.class, ".*Suffix$ );Once you have the array of classes you can instantiate them with relfection, but I beleive that only works if your class has an empty constructor.

/** * A class to find all subclasses of a given <code>Class</code> or interface. * */publicclassSubclasses {

/** * Find all subclasses of the given <code>Class</code> or interface by * loading all classes on the class path. * * @param targetType the superclass of all returned classes. * @return an array of all subclasses of <code>targetType</code> */publicstaticClass[] of( ClasstargetType ) {returnof( targetType, ".*" );

/** * Answers an <code>Iterator</code> over fully qualified <code>Class</code> * names found on the classpath. * @return an <code>Iterator</code> over the elements in this list */publicIteratorclassNameIterator() {returnclassNames.iterator();

}

/** * Answers an <code>ArrayList</code> of all <code>Class</code> names found * on the classpath. * @return an <code>ArrayList</code> of class names. */publicArrayListgetClassNames() {returnclassNames;

I've written a plugin loader for a PVR software application I'm writing. Here is the code, it'll scan through all jars in a given directory and find me classes inside those jars which implement my plugin interface.

The file scanning code above is flawed in that it won't work correctly where jar files have a class-path entry in the manifest. This invisibly adds additional jar files to the class path.

There are two main uses for this type of functionalitya) in an IDE (for refactoring or other developer search aids). In this case you will already know where all the relevant source and class files are located and can search them pretty much as described in the other posts.

b) You want to find all available implementations for some service. In this case you (the service implementors) explicitly list the implementing classes in a text resource. The text resources are located using ClassLoader.getResources() as this will allow each jar file or directory tree on the class path to have an instance of the resource. Merge all the results you thus obtain. I think there is even a semi-standard implementation of this.

This version of ClassPath fixes that issue ( use with SubClasses above ) by scanning the manifest and digging through any Class-Path entries.

note: javac assumes Class-Path entries are relative to the path of the jar they are in, so I do as well!! I have tested this with a main.jar, a second.jar referenced in main's manifest, and a third.jar referenced in second.jar's manifest.

/** * Answers an <code>Iterator</code> over fully qualified <code>Class</code> * names found on the classpath. * @return an <code>Iterator</code> over the elements in this list */publicIteratorclassNameIterator() {returnclassNames.iterator();

}

/** * Answers an <code>ArrayList</code> of all <code>Class</code> names found * on the classpath. * @return an <code>ArrayList</code> of class names. */publicArrayListgetClassNames() {returnclassNames;

Jeff's JUtils plugin system won't work for me because it only searches in one place.(also I'm worried it might not work with webstart (I saw several uses of File-based access that weren't shielded by backup plans using non-File mechanisms...)?)

Duncan's ClassPath class is what I just spent 15 minutes searching Sun's JDK for - and I am disappointed that: a. it doesn't exist (why the heck not?!??!) b. ...and the whole of the Package class in java.lang.reflect. That thing is an abomination! Not only is it hardcoded to assume you only ever have ONE manifest for a single package (not only is it possible to have arbitrarily many, but in fact is common) but it doesn't have the most obvious of all methods for a Package class - getClassNames() . (In fact, it seems it's just part of the last-minute hacking Sun did to make J2EE a little less painful - Package is not *really* "Package", it's really a class called "ManifestFilePackageEntry" that someone was too lazy to type the full name for )

But rather than matching subclasses, I'm after instances. So, I was wondering if perhaps I could take Duncan's ClassPath and make an alternative to his SubClasses class which was a "front-end" to a range of searches...so it would include his SubClasses lookup, but also an instances lookup, etc.

And then make it all available as a tiny self-contained JAR, with no reserved rights other than authorship details...

java-gaming.org is not responsible for the content posted by its members, including references to external websites,
and other references that may or may not have a relation with our primarily
gaming and game production oriented community.
inquiries and complaints can be sent via email to the info‑account of the
company managing the website of java‑gaming.org