1
\$\begingroup\$

Edit: Clarification:

I want to create a named module during runtime and put dynamically loaded classes into the created module.

I am attempting to build a framework that allows for code generation that is compatible with Java 9's module system. I require the ability to load some generated byte code into a "virtual" module.

From what I can tell after looking though the Java code there are no exported and public methods that allow me to do anything like this, but I am sure I am missing something.

For an example, let's say this class is generated for the module "handler".

package handler;

public class ModHandler{
    public static String fireEvent(){
        return "This is a string from the generated module!";
    }
}

How do I make the "handler" module and load the bytecode into it? How would you add exports and requires into the module? I do not want to write anything to the disk to implement this.

\$\endgroup\$
3
  • 1
    \$\begingroup\$ stackoverflow.com/questions/2946338/… \$\endgroup\$
    – Bálint
    Commented Jan 5, 2018 at 7:49
  • \$\begingroup\$ That is not the problem here, I understand code generation/modification and class loading before Java 9. I need to know how to load them into a programicly defined module. \$\endgroup\$
    – gudenau
    Commented Jan 5, 2018 at 15:50
  • \$\begingroup\$ is this question still active? or is it already answered in stackoverflow.com/questions/46112809/… \$\endgroup\$ Commented May 28, 2018 at 13:11

1 Answer 1

1
\$\begingroup\$

You have to create a ModuleLayer from a Configuration. This requires a Set of Paths to pass to a ModuleFinder instance that can be created with ModuleFinder.of.

This example lists the jars in plugins and loads the modules.

// List all jar files in ./plugins
File[] pluginFiles = new File("plugins").listFiles((f,n)->n.endsWith(".jar"));
// Convert to Paths
Arrays.stream(pluginFiles).map(File::toPath).collect(Collectors.toSet());
// Create a module finder from those jars
ModuleFinder finder = ModuleFinder.of(Set.of(pluginFiles));
// Get the boot config
Configuration parentConfig = ModuleLayer.boot().configuration();
// Create a new configuration
Configuration configuration = parentConfig.resolve(
    finder,
    ModuleFinder.of(),
    // This gets the names of all the modules and tells the Config to load them
    finder.findAll().stream().map(mr->mr.descriptor().name()).collect(Collectors.toList())
);
// Create the ModuleLayer, you can now interact with the modules
ModuleLayer layer = ModuleLayer.boot().defineModulesWithOneLoader(configuration, ClassLoader.getSystemClassLoader());

This was so much harder to find than one might think, with this you can create a custom ModuleFinder and do weird and wonderful things.

\$\endgroup\$
2
  • \$\begingroup\$ Glad to hear that you found a solution! Don't forget to mark it as accepted - it helps others who may run into the same or similar problems. \$\endgroup\$
    – Pikalek
    Commented May 30, 2018 at 17:48
  • 1
    \$\begingroup\$ I did not even try to because I am used to a 24 hour delay before I can do that. :-P \$\endgroup\$
    – gudenau
    Commented May 30, 2018 at 22:36

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .