Find Java classes implementing an interface [duplicate] - java

This question already has answers here:
How can I get a list of all the implementations of an interface programmatically in Java?
(11 answers)
Closed 9 years ago.
Some time ago, I came across a piece of code, that used some piece of standard Java functionality to locate the classes that implemented a given interface. I know the functions were hidden in some non-logical place, but they could be used for other classes as the package name implied. Back then I did not need it, so I forgot about it, but now I do, and I can't seem to find the functions again. Where can these functions be found?
Edit: I'm not looking for any IDE functions or anything, but rather something that can be executed within the Java application.

Awhile ago, I put together a package for doing what you want, and more. (I needed it for a utility I was writing). It uses the ASM library. You can use reflection, but ASM turned out to perform better.
I put my package in an open source library I have on my web site. The library is here: http://software.clapper.org/javautil/. You want to start with the with ClassFinder class.
The utility I wrote it for is an RSS reader that I still use every day, so the code does tend to get exercised. I use ClassFinder to support a plug-in API in the RSS reader; on startup, it looks in a couple directory trees for jars and class files containing classes that implement a certain interface. It's a lot faster than you might expect.
The library is BSD-licensed, so you can safely bundle it with your code. Source is available.
If that's useful to you, help yourself.
Update: If you're using Scala, you might find this library to be more Scala-friendly.

Spring can do this for you...
BeanDefinitionRegistry bdr = new SimpleBeanDefinitionRegistry();
ClassPathBeanDefinitionScanner s = new ClassPathBeanDefinitionScanner(bdr);
TypeFilter tf = new AssignableTypeFilter(CLASS_YOU_WANT.class);
s.addIncludeFilter(tf);
s.scan("package.you.want1", "package.you.want2");
String[] beans = bdr.getBeanDefinitionNames();
N.B. The TypeFilter is important if you want the correct results!
You can also use exclusion filters here instead.
The Scanner can be found in the spring-context jar, the registry in spring-beans, the type filter is in spring-core.

I really like the reflections library for doing this.
It provides a lot of different types of scanners (getTypesAnnotatedWith, getSubTypesOf, etc), and it is dead simple to write or extend your own.

The code you are talking about sounds like ServiceLoader, which was introduced in Java 6 to support a feature that has been defined since Java 1.3 or earlier. For performance reasons, this is the recommended approach to find interface implementations at runtime; if you need support for this in an older version of Java, I hope that you'll find my implementation helpful.
There are a couple of implementations of this in earlier versions of Java, but in the Sun packages, not in the core API (I think there are some classes internal to ImageIO that do this). As the code is simple, I'd recommend providing your own implementation rather than relying on non-standard Sun code which is subject to change.

Package Level Annotations
I know this question has already been answered a long time ago but another solution to this problem is to use Package Level Annotations.
While its pretty hard to go find all the classes in the JVM its actually pretty easy to browse the package hierarchy.
Package[] ps = Package.getPackages();
for (Package p : ps) {
MyAno a = p.getAnnotation(MyAno.class)
// Recursively descend
}
Then just make your annotation have an argument of an array of Class.
Then in your package-info.java for a particular package put the MyAno.
I'll add more details (code) if people are interested but most probably get the idea.
MetaInf Service Loader
To add to #erickson answer you can also use the service loader approach. Kohsuke has an awesome way of generating the the required META-INF stuff you need for the service loader approach:
http://weblogs.java.net/blog/kohsuke/archive/2009/03/my_project_of_t.html

You could also use the Extensible Component Scanner (extcos: http://sf.net/projects/extcos) and search all classes implementing an interface like so:
Set<Class<? extends MyInterface>> classes = new HashSet<Class<? extends MyInterface>>();
ComponentScanner scanner = new ComponentScanner();
scanner.getClasses(new ComponentQuery() {
#Override
protected void query() {
select().
from("my.package1", "my.package2").
andStore(thoseImplementing(MyInterface.class).into(classes)).
returning(none());
}
});
This works for classes on the file system, within jars and even for those on the JBoss virtual file system. It's further designed to work within standalone applications as well as within any web or application container.

In full generality, this functionality is impossible. The Java ClassLoader mechanism guarantees only the ability to ask for a class with a specific name (including package), and the ClassLoader can supply a class, or it can state that it does not know that class.
Classes can be (and frequently are) loaded from remote servers, and they can even be constructed on the fly; it is not difficult at all to write a ClassLoader that returns a valid class that implements a given interface for any name you ask from it; a List of the classes that implement that interface would then be infinite in length.
In practice, the most common case is an URLClassLoader that looks for classes in a list of filesystem directories and JAR files. So what you need is to get the URLClassLoader, then iterate through those directories and archives, and for each class file you find in them, request the corresponding Class object and look through the return of its getInterfaces() method.

Obviously, Class.isAssignableFrom() tells you whether an individual class implements the given interface. So then the problem is getting the list of classes to test.
As far as I'm aware, there's no direct way from Java to ask the class loader for "the list of classes that you could potentially load". So you'll have to do this yourself by iterating through the visible jars, calling Class.forName() to load the class, then testing it.
However, it's a little easier if you just want to know classes implementing the given interface from those that have actually been loaded:
via the Java Instrumentation framework, you can call Instrumentation.getAllLoadedClasses()
via reflection, you can query the ClassLoader.classes field of a given ClassLoader.
If you use the instrumentation technique, then (as explained in the link) what happens is that your "agent" class is called essentially when the JVM starts up, and passed an Instrumentation object. At that point, you probably want to "save it for later" in a static field, and then have your main application code call it later on to get the list of loaded classes.

If you were asking from the perspective of working this out with a running program then you need to look to the java.lang.* package. If you get a Class object, you can use the isAssignableFrom method to check if it is an interface of another Class.
There isn't a simple built in way of searching for these, tools like Eclipse build an index of this information.
If you don't have a specific list of Class objects to test you can look to the ClassLoader object, use the getPackages() method and build your own package hierarchy iterator.
Just a warning though that these methods and classes can be quite slow.

Related

How to use Java Reflections for the "current" application?

The documentation for Reflections gives the first line on how to use Reflections:
Reflections reflections = new Reflections("com.my.project");
Except i don't know the name of the package. This is a piece of library code that should just be able to scan everything in the current package.
What is the Reflections equivalent of the .NET:
//Find all methods in all classes tagged with #Test annotation,
//and add them to a list.
List<MethodInfo> testMethods = new ArrayList<>();
//Enumerate all assemblies in the current application domain
for (Assembly a : AppDomain.currentDomain.getAssemblies()) {
//Look at each type (i.e. class) in the assembly
for (Type t : a.getTypes()) {
...
}
}
in other words, the "current" package? Or in the parlance of .NET
AppDomain.currentDomain
Edit:
Is it a duplicate? No.
Is it not a programming question? No
Does it need details or clarity? No
Does it need more focus? No
Is it opinion based? No
Bonus Reading
Get all methods with a particular annotation in a package (explains what a package is)
How to find annotated methods in a given package? (explains what a package is)
And the final straw:
java.lang.NoClassDefFoundError: org/slf4j/LoggerFactory even though I have the right dependencies
Java's concept of 'package' is much weaker than .net. In Java, the package containing a class is, for most purposes, just the prefix of the classes name.
OSGi, and recent Java versions with Modules, have a stronger model.
If you read down the documentation to https://github.com/ronmamo/reflections#scan, you will see that there are a number of filters that you can apply to control what this library looks at. If you are writing a library, you can either expose that API to your callers and let them tell you what classes to look at, or decide for yourself what to look at. But there is not requirement to have a single focal Java package as far as I see in that documentation.
Calling this.getClass().getPackage().getName() will mean that reflection is only looking at your code, not the rest of the application using your library.
Cannot be done.
Java does not have a reflection system.
Research Effort
Get all methods with a particular annotation in a package (Question isn't about the current package. Accepted answer uses 3rd party library.)
Java seek a method with specific annotation and its annotation element (Question is about a specific class, rather than finding the classes)
How to find annotated methods in a given package?
How to run all methods with a given annotation?
getConstructor with no parameters
Call Methods at Runtime Using Java Reflection
JavaDocs - Invoking Methods
Default access modifier for a Java constructor
Can you find all classes in a package using reflection?
Get all methods with a particular annotation in a package (explains what a package is)
How to find annotated methods in a given package? (explains what a package is)
Additional research effort
java.lang.NoClassDefFoundError: org/slf4j/LoggerFactory even though I have the right dependencies
Oracle: Handling Initialization Status With Event Handlers
how to register a java class if the static initializer isn't called till the class is referenced
Dynamic object registration in Java
getConstructor with no parameters
Load Jar dynamically and register class(es) in applicationContext at runtime
Is it possible to determine descendants solely through Java reflection API?
Call Methods at Runtime Using Java Reflection
JavaDocs - Invoking Methods
At runtime, find all classes in a Java application that extend a base class
Default access modifier for a Java constructor
Find Java classes implementing an interface
Finding all classes implementing a specific interface
How does JUnit find tests?
Book: Unit Testing in Java
[2/28/1998: JUnit 1.0][2]
JUnit Cookbook
How can I get a list of all the implementations of an interface programmatically in Java?
How can I get all Class files in a specific package in Java?
Class Loaders in Java
How can I enumerate all classes in a package and add them to a List?
Java Reflection - Get List of Packages
Getting the list of packages in a java project
Tool to convert java to c# code
Package Initialization in Java
How to write a package-level static initializer in Kotlin?
https://stackoverflow.com/questions/72795950/java-initialize-all-classes-in-package-without-knowing-names
https://github.com/classgraph/classgraph
What is an initialization block?
Package Initialization in Java

Java: find classes with certain base type on program startup

I have a Java program (an Eclipse plug-in to be specific), which is using several JAR files (which I can control). One of the core JAR files defines an abstract class called Strategy. When the user starts the program, the program needs to know all sub classes of Strategy, that are on the program ClassPath.
As I described in this StackOverflow question, I tried to use static initializer blocks on the sub classes, so that they auto-register themselves in a registry. This approach is not working since the static initalizers are not executed before I explicitly use the class.
Is there any other way to find all classes with a certain base type that are on the current ClassPath?
I can think of the following solutions:
traverse all JARs in a specific directory and check the classes they contain
create a file which is loaded on program start-up and read the class names from that
I can implement both of them myself (so I do not ask for any code samples here). I merely want to know if there is another option I am missing. Any in-class solution (like the one I tried with static initializers) would be greatly appreciated.
If you're open to using a third-party library, Reflections seems to be the best fit here. It's a Java runtime metadata analysis library and is like geared to do this. From their website:
Using Reflections you can query your metadata such as:
get all subtypes of some type
get all types/constructos/methods/fields annotated with some annotation, optionally with annotation parameters matching
get all resources matching matching a regular expression
get all methods with specific signature including parameters, parameter annotations and return type
All you need is to create a configured instance of Reflections in your StrategyRegistrar class as
Reflections reflections = new Reflections(
new ConfigurationBuilder()
.setUrls(ClasspathHelper.forPackage("com.your.app.strategies.pkg"))
.setScanners(new SubTypesScanner())
);
And, then simply fire a query like
Set<Class<? extends Strategy>> strategies =
reflections.getSubTypesOf(com.your.app.strategies.pkg.Strategy.class);

Finding all classes implementing a specific interface [duplicate]

This question already has answers here:
Find Java classes implementing an interface [duplicate]
(9 answers)
Closed 6 years ago.
I am in the process of developing an application (Quartz scheduler) where we have a job class which is responsible for actually executing the work and we need to tell/pass the name of the job class while creating a trigger in the Quartz scheduler.
I want to provide an extension point to all who want to use the API (beside the some generic jobs which I will provide as part of the API). The idea is to create an (marker) interface and if any one wants to declare their class as scheduler job class, all they have to do is, to (declare to) implement the interface.
I am not sure how I can find which classes are following the contract (by implementing the interface) so that I can show them to the user who want to schedule a trigger in the scheduler.
My requirement is not to load the classes at run time but to show user list of classes which implement the required interface so that user can select the class and class name can be passed to the scheduler. It's the Quartz scheduler which at the end will be responsible to create an instance of class.
Can any one suggest how I can achieve the above goal or is there any other better way to achieve what I am trying to do?
Edit
I went through the doc of ServiceLoader and it seems that for implementing a service one has to create a file in the META-INF folder with the name of the implementation class, which leads me to think that if the user of my API wants 20 different implementations, he has to put 20 entries in the file which for me seems a lot of extra work for the end user since each job class will be created for executing a specific job and there can be 100s of job classes.
Please correct me if my assumption is wrong.
You can find an answer here.
I can suggest using org.reflections
You can take a look at it here
Reflections reflections = new Reflections("com.mycompany");
Set<Class<? extends MyInterface>> classes = reflections.getSubTypesOf(MyInterface.class);
I had a similar need where I wanted to make sure that any classes created that implemented a certain interface were always truly serializable. I created a JavaClassFinder which walks through all directories in the classpath, and finds all classes assignable to the interface I cared about. Here is a code snippet:
public <T> List<Class<? extends T>> findAllMatchingTypes(Class<T> toFind) {
foundClasses = new ArrayList<Class<?>>();
List<Class<? extends T>> returnedClasses = new ArrayList<Class<? extends T>>();
this.toFind = toFind;
walkClassPath();
for (Class<?> clazz : foundClasses) {
returnedClasses.add((Class<? extends T>) clazz);
}
return returnedClasses;
}
I'm happy to share the code with you if it helps. The only draw back is that this will only handle .class files -- I didn't add the feature to unzip .jars and read class files from there. (But it wouldn't be a huge project to add that.)
UPDATE: I checked my source code for the above, and found it depends on a lot of helper classes in our standard utility library. To make it easier, I zipped up all the code needed, which you can download from JavaClassFinder.zip. This will set up directly in Eclipse, and you can take whatever portions of the code you need.
You will find a JUnit3 test in the project, called JavaClassFinderTest.java, which shows you the features and usage of the JavaClassFinder class. The only external dependency needed to run the Junit test is Junit.
Basic usage of this utility:
JavaClassFinder classFinder = new JavaClassFinder();
List<Class<? extends MyTagInterface>> classes = classFinder.findAllMatchingTypes(MyTagInterface.class);
This will give you a List which contains any classes in the classpath which are assignable from the "MyTagInterface.class" (for example). Hope this helps.
Probably the best (standard) way to do this by using the Java SPI mechanism, see Javadoc. The inconvenient (which is also a nice feature) is that it expects Jars that define extensions to list them in META-INF/services/your.fully.qualified.Interface.
The only other way I can think of would be to wall through all ClassLoaders in hope you'll be able to list the files in there, load the class files, and see if they implement your interface or not - which is not a nice thing to do.
I think that org.reflections is a proper solution as mentioned by Alex Stybaev, you don't need to reference the classes in a property file.
Another approach (which I would take) is Spring, since I am using Spring anyway for my applications and therefore wouldn't need any additionally dependencies.
You can find hints for solving your problem with Spring (and alternatives in the other comments or answers) here:
http://mcoj.wordpress.com/2009/03/13/classpath-scanning/
http://www.sleberknight.com/blog/sleberkn/entry/20080623
http://www.terminalstate.net/2007/12/scanning-class-path-with-spring-25.html
In the comments of your question heikkim and polypiel also link to questions with have answers for solving it with Spring:
https://stackoverflow.com/a/8166959/734687
https://stackoverflow.com/a/1415338/734687
From the answers of Find Java classes implementing an interface, I used http://software.clapper.org/javautil/: Very fast, very useful.
To do so in pure java, the most correct answer is already voted (from sam goldberg apr 10,2012)
However full code of his is unnecessarily complex. I used his idea and pushed ClassFinder there:
http://icedtea.classpath.org/hg/icedtea-web/file/0527ad4eb2dd/netx/net/sourceforge/jnlp/controlpanel/ClassFinder.java
Note - this will work in stand alone application (or any application using regular classpath with jars and dirs) not in ServerContainer.
if your app is running in webserver, you need to know location of your war/ear and search there. Or you have to ask your parent classlaoder where it is he getting yours (and other) sources.
Second note - I'm filtering final locations classes to match only netx and icedtea-web as I do not wont dependencies searched. So if you need to include rt.jar please, rmeove thsoe filters. Or remove bootclasspath at all if you on contrary do not need it at all.

How can I run my code upon class load?

Is there a feasible way to get my own code run whenever any class is loaded in Java, without forcing the user explicitly and manually loading all classes with a custom classloader?
Without going too much into the details, whenever a class implementing a certain interface read its annotation that links it with another class, and give the pair to a third class.
Edit: Heck, I'll go to details: I'm doing an event handling library. What I'm doing is having the client code do their own Listener / Event pairs, which need to be registered with my library as a pair. (hm, that wasn't that long after all).
Further Edit: Currently the client code needs to register the pair of classes/interfaces manually, which works pretty well. My intent is to automate this away, and I thought that linking the two classes with annotations would help. Next, I want to get rid of the client code needing to keeping the list of registrations up to date always.
PS: The static block won't do, since my interface is bundled into a library, and the client code will create further interfaces. Thus, abstract classes won't do either, since it must be an interface.
If you want to base the behavior on an interface, you could use a static initializer in that interface.
public interface Foo{
static{
// do initializing here
}
}
I'm not saying it's good practice, but it will definitely initialize the first time one of the implementing classes is loaded.
Update: static blocks in interfaces are illegal. Use abstract classes instead!
Reference:
Initializers (Sun Java Tutorial)
But if I understand you right, you want the initialization to happen once per implementing class. That will be tricky. You definitely can't do that with an interface based solution. You could do it with an abstract base class that has a dynamic initializer (or constructor), that checks whether the requested mapping already exists and adds it if it doesn't, but doing such things in constructors is quite a hack.
I'd say you cleanest options are either to generate Code at build time (through annotation processing with apt or through bytecode analysis with a tool like asm) or to use an agent at class load time to dynamically create the mapping.
Ah, more input. Very good. So clients use your library and provide mappings based on annotations. Then I'd say your library should provide an initializer method, where client code can register classes. Something like this:
YourLibrary.getInstance().registerMappedClasses(
CustomClass1.class,
CustomClass2.class,
CustomClass3.class,
CustomClass4.class
)
Or, even better, a package scanning mechanism (example code to implement this can be found at this question):
YourLibrary.getInstance().registerMappedClassesFromPackages(
"com.mycompany.myclientcode.abc",
"com.mycompany.myclientcode.def"
)
Anyway, there is basically no way to avoid having your clients do that kind of work, because you can't control their build process nor their classloader for them (but you could of course provide guides for classloader or build configuration).
If you want some piece of code to be run on any class loading, you should:
overwrite the ClassLoader, adding your own custom code at the loadClass methods (don't forget forwarding to the parent ClassLoader after or before your custom code).
Define this custom ClassLoader as the default for your system (here you got how to do it: How to set my custom class loader to be the default?).
Run and check it.
Depending on what kind of environment you are, there are chances that not all the classes be loaded trouugh your custom ClassLoader (some utility packages use their own CL, some Java EE containers handle some spacific areas with specific classLoaders, etc.), but it's a kind of aproximation to what you are asking.

Java reflecting subclasses

I have a class in Java, I wish to reflect all subclasses of this class, how would I do this?
In this specific case, all subclasses are in the same package, and only subclasses are in this package, so an equivalent solution is to fetch all classes in a package.
I think you could do this using spring's org.springframework.core.io.support.PathMatchingResourcePatternResolver. At least I know you can use it to find all classes with a certain annotation. Finding subclasses seems to be a very similar problem I'd expect to work as well.
Here's some (untested) code to get you started:
PathMatchingResourcePatternResolver match = new PathMatchingResourcePatternResolver();
MetadataReaderFactory f = new SimpleMetadataReaderFactory();
List<Class<?>> matches = ...;
for (Resource r : match.getResources("classpath*:com/example/**/*.class")) {
AnnotationMetadata meta = f.getMetadataReader(r).getAnnotationMetadata();
if (meta.getAnnotationsTypes().contains(MyAnnotation.class.getName()) {
matches.add(Class.forName(meta.getClassName()));
}
}
return matches;
As you might see, it's basically the idea describe by Stephen C
See this answer how to locate all classes in a package.
Next, you'll need a list of all packages which isn't trivial in the general case. But if you only use the standard classloader (which solely relies on the classpath), you can get the system property java.class.path and analyze that to get all JARs. Open them to list the content and then you'll know the class names.
It is possible to do (messily) in some cases; e.g. if your application's classes are loaded from local directories or JAR files. Basically, you need to map the package name to a pathname and use the File and/or ZipFile APIs to look for files in the relevant "directory" whose name ends with ".class". Then you use Class.forName() load the corresponding classes (trying to avoid initializing them), and use clazz.isAssignableFrom(subclazz) to see which of them are subclasses.
But this won't work in all cases. One problem is that the ClassLoader API does not support iterating over all of the classes / packages that it could load.
I would recommend that you find an alternative approach to the problem you are tying to address.
EDIT - in response to this comment.
It seems this is a massive fault in the java reflection API
I understand that the omission is deliberate. If the classloader API did include a method to give all classes in a package, it would limit the schemes that can be used for classloading. For example, URLClassLoader would not be implementable for 'http:' URLs because the HTTP protocol does not provide a standard way to retrieve the entries in a directory.
Besides, there are few situations where a production application really needs to reflectively find all classes in a package.

Categories

Resources