I want to load classes from a module (.jmod) file at runtime into the application memory.
I know that we can easily load classes from a (.jar) file using 🙂
ClassLoader loader = URLClassLoader.newInstance(new URL[]{ jarFile.toURL() });
The total code snippet can be found at this-repo in src omega.deassembler.JarLoader class
But the problem is URLClassLoader is unable to read the modules(.jmod).
So is there any other internal class or library to load classes from a module(.jmod) file.
Actually, I am creating an IDE and this-repo is a part of it for loading content-assist hints.
Earlier, I was using javap command to disassemble and load hints (see omegaide on github).
But this technique consumes much time, so i am writing it again!
Thank You.
Advertisement
Answer
This is not exactly the answer but a method to make URLClassLoader
usable when it has to read modules.
Earlier URLClassLoader was throwing this exception when trying to read a module file(.jmod)
when omitting the module-info
Exception in thread "main" java.lang.NoClassDefFoundError: com/sun/javafx/event/DirectEvent (wrong name: classes/com/sun/javafx/event/DirectEvent) at java.base/java.lang.ClassLoader.defineClass1(Native Method) at java.base/java.lang.ClassLoader.defineClass(ClassLoader.java:1010) etc
and when including the meta-info
Exception in thread "main" java.lang.NoClassDefFoundError: classes/module-info is not a class because access_flag ACC_MODULE is set
This means that it is unable to identify the directory system inside the jmod file.
So as we know, that a simple jar file contains classes and resources only (Just exclude meta-info).
And in a module file(.jmod), all the classes are placed inside the classes folder and all the resources are placed in the resources folder.
Thus, We can create a temporary jar file say “modular-jar.jar” with the contents of classes and resources from the module file,
and then using standard URLClassLoader we can load it onto the classpath
and then can immediately delete the file.
This will just work at least in my case
Here’s the code snippet
public static synchronized JarLoader prepareModule(String modulePath){ try{ ZipFile moduleFile = new ZipFile(modulePath); ZipOutputStream zipOutputStream = new ZipOutputStream(new FileOutputStream("readable-module-data.jar")); for(Enumeration enums = moduleFile.entries(); enums.hasMoreElements();){ ZipEntry entry = (ZipEntry)enums.nextElement(); String name = entry.getName(); if((name.startsWith("classes") && !name.contains("module-info")) || name.startsWith("resources")){ zipOutputStream.putNextEntry(new ZipEntry(name.substring(name.indexOf('/') + 1))); InputStream in = moduleFile.getInputStream(entry); while(in.available() > 0) zipOutputStream.write(in.read()); zipOutputStream.flush(); } } zipOutputStream.close(); } catch(Exception e){ e.printStackTrace(); } return new JarLoader("readable-module-data.jar"); }