javapackager - partially self-contained apps in JDK 9

Chris Bensen chris.bensen at
Tue Apr 25 18:32:26 UTC 2017

> On Apr 11, 2017, at 10:43 AM, Alan Snyder <javalists at> wrote:
> I have run into a problem in moving my macOS apps from JDK 8 to 9. The issue relates to using MySQL via JDBC.
> The connector class name is fixed. The class is loaded using Class.forName(). However, there can be different versions
> of the connector in different JAR files, and the proper version might need to be synced with the currently installed version
> of MySQL.
> In JDK 8, I used the extension mechanism to load the MySQL connector JAR rather than building this JAR into the bundled app.
> My thinking was that the connector might need to be updated in sync with the database and I should not have to rebuild apps to do that.
> In JDK 9, the extension mechanism is gone. I have not found any way to achieve the equivalent effect. It seems that javapackager
> controls the setting of the CLASSPATH. I have not found an option that would allow me to extend the CLASSPATH with a directory
> where the connector JAR could be found. Is there a way to do this?
>  Alan

Are you including the connector JAR in the app image?

I think you could set the classpath if you us ant-javafx.jar:

<fx:jvmuserarg name=“-classpath" value=“...”/>

but honestly I’ve never tried it with JDK 9.

A JDK 9 way of dynamically loading this would be to create a Layer. Here’s some semi working code you could use:

    public Plugin loadPlugin(String module, String classname) {
        Plugin result = null;
        Configuration cf = resolve(file.getAbsoluteFile().getParentFile().toPath(), name);
        ClassLoader scl = ClassLoader.getSystemClassLoader();
        Layer layer = Layer.boot().defineModulesWithOneLoader(cf, scl);
        ClassLoader cl = layer.findLoader(name);

        try {
            result = createPlugin(layer, name, classname);
        catch (Exception e) {
            System.out.println("oh no!" + e.toString());

        return result;

    private static Configuration resolve(Path modulepath, String... roots) {
        ModuleFinder finder = ModuleFinder.of(modulepath);
        return Layer.boot()
            .resolve(finder, ModuleFinder.of(), Set.of(roots));

    private static Plugin createPlugin(Layer layer, String mn, String mc) throws Exception {
        ClassLoader loader = layer.findLoader(mn);
        Class<?> c = loader.loadClass(mc);
        Plugin p = (Plugin)c.getConstructor().newInstance();
        return p;


More information about the openjfx-dev mailing list