Skip to content

Implement loading ClassLoaderHandler from Java’s ServiceLoader.#266

Merged
lukehutch merged 1 commit into
classgraph:masterfrom
michael-simons:issue/add-support-for-dynamic-classloaderhandler
Oct 25, 2018
Merged

Implement loading ClassLoaderHandler from Java’s ServiceLoader.#266
lukehutch merged 1 commit into
classgraph:masterfrom
michael-simons:issue/add-support-for-dynamic-classloaderhandler

Conversation

@michael-simons

Copy link
Copy Markdown
Contributor

The ClassLoaderHandler promises in it's JavaDoc that additional handlers can be loaded through the standard Java SPI. That's not the case.

This PR add this feature and additionally fixes the doc. Please see the single commit message for more detail (quoted below).

All the standard handlers could maybe be loaded through the SPI as well, but to keep the order one would have to add one additional interface method and I understand ClassGraph should still support Java 7, so I didn't add a default interface method.

Also, thanks for your work on ClassGraph, we are using it in Neo4j-OGM and are currently in the process of upgrading from FastClasspathScanner code.

This commit adds loading of additional ClassLoaderHandler from Java’s Serviceloader SPI.

The default list of handlers is now created in a static initializer block and than supplemented by a list of dynamically loaded handlers.
To use the the handlers from the SPI, ClassLoaderHandlerRegistryEntry had to have a new constructor, taking, taking in the prepopulated handler.

This commit adds loading of additional ClassLoaderHandler from Java’s Serviceloader SPI.

The default list of handlers is now created in a static initializer block and than supplemented by a list of dynamically loaded handlers.
To use the the handlers from the SPI, ClassLoaderHandlerRegistryEntry had to have a new constructor, taking, taking in the pre populated handler.
@lukehutch

lukehutch commented Oct 25, 2018

Copy link
Copy Markdown
Member

Great contribution, thanks! Looks good to me.

Yes, it looks like the ability to register custom ClassLoaderHandler classes got broken in the changeover from FastClasspathScanner to ClassGraph, and I hadn't spotted that before.

What ClassLoader are you trying to support here? Is it your own custom ClassLoader? Is there a possibility that it will be useful to other projects to check in your own ClassLoaderHandler as part of ClassGraph itself, or is it really just internal-only?

I just barely pushed out a new version of ClassGraph an hour ago, so I might wait to push this out as a new version until I have some other things to release as well, but let me know if you need a release with any urgency.

Glad to know Neo4j-OGM is getting some good use out of FastClasspathScanner/ClassGraph! The upgrade to ClassGraph will be worth the effort, it is significantly more robust, capable, optimized, and futureproof (e.g. supporting JPMS) compared to FCS.

@lukehutch lukehutch merged commit fc3fd11 into classgraph:master Oct 25, 2018
@michael-simons

Copy link
Copy Markdown
Contributor Author

Wow, that was fast! Thanks a lot!

And yes, I'd like to see another class loader handler, for Spring Boots Devtools (See RestartClassLoader and [https://docs.spring.io/spring-boot/docs/current/reference/html/using-boot-devtools.html](Spring Boot Devtools)).

Our current branch using ClassGraph fails in Spring Boot Apps running Devtools when loading classes to ClassGraph.
Even though we specify the class loader to use, currently ClassGraph takes the parent one while the application get's all the classes from RestartClassLoader. IMHO it's only a matter of parent or child first, but I'll give it some more thought before I submit another PR.

@lukehutch

Copy link
Copy Markdown
Member

ClassGraph has support for different delegation modes (parent first or child first), but every classloader I have ever come across uses parent first delegation (for the same reason that you should never have the current directory "." in your commandline path before "/bin", "/usr/local/bin", etc.).

It's possible there's some other weird or complex ordering bug in ClassGraph too -- I tried to guess the correct order for pulling paths from classloaders, but I'm sure it's not correct for every situation.

It's a very simple task to write a new ClassLoaderHandler, assuming the classloader has a list of paths or URLs available somewhere in its fields or methods. The existing ClassLoaderHandlers provide a lot of examples. In a couple of cases though I had to stop a running program in a debugger and explore the reachable object space to figure out where the classpath was stored (sometimes 6 or 8 steps removed from the classloader itself).

I know next to nothing about Spring Boot, so can't help much with the specifics of RestartClassLoader, but I'd really appreciate any further contributions you want to send in! Thanks!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants