Hello. I am trying to run a jshell with a system classloader containing the classes from a fat-jar produced by the gradle plugin task. The system classloader is managed by the property java.system.class.loader, but the problem is that it needs a classloader with a constructor having a single parameter of parent classloader. I believe that it is possible to extract such classloaders from JarLauncher and WarLauncher in org.springframework.boot.loader package. Then it would be possible to launch the jshell somewhat like this:

jshell --class-path boot.jar -RDjava.system.class.loader=org.springframework.boot.loader.JarLauncherClassLoader

Do you mind me doing this refactoring? Found a related issue – https://github.com/spring-projects/spring-boot/issues/1812

Comment From: wilkinsona

Have you considered implementing your own ClassLoader that delegates to LaunchedURLClassLoader?

Comment From: faucct

Yes, I have considered it, but it would require to compile against the package and use a bunch of protected *Launcher methods. I think that extracting class-loaders seems like an intuitive direction to follow and believe that this would be much easier to integrate.

Comment From: faucct

Here is the code I had to write to extract the class-loader from the protected methods and I think that it is wrong to go that way:

new org.springframework.boot.loader.JarLauncher(
        new org.springframework.boot.loader.archive.JarFileArchive(new java.io.File(
                "/opt/ranker/lib/ranking-web-1.0-SNAPSHOT.jar"
        ))
) {
    {
        if (!isExploded()) {
            org.springframework.boot.loader.jar.JarFile.registerUrlProtocolHandler();
        }
        try {
            Thread.currentThread().setContextClassLoader(createClassLoader(getClassPathArchivesIterator()));
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
    }
};

Comment From: faucct

So do you mind me refactoring that?

Comment From: wilkinsona

I don't think we're ready for that. Support for jshell hasn't been a goal of the project. That could change of course, but I don't think we should change public API for something that we may not want to support. I'll flag this issue for the team to discuss.

Comment From: faucct

What exactly is public API in the org.springframework.boot.loader package? I could try leaving it intact.

Comment From: wilkinsona

It's not just the public API. It's also the ongoing burden of maintaining support, testing it, and the ways that it would limit what we can change in the future. Thanks for your enthusiasm, but, to avoid wasted effort, please give us some time to discuss this before working on any changes as we may not accept them.

Comment From: faucct

Meanwhile, what is the proper way to compile against the files in the package?

Comment From: wilkinsona

Add a dependency on org.springframework.boot:spring-boot-loader.

Comment From: wilkinsona

We discussed this today and the team are in agreement that this isn't something that we want to support. Thanks anyway for the suggestion.