Closed gudenau closed 1 year ago
@gudenau. Yes, when developing with named JPMS modules the sun.misc.Unsafe class is not accessible without requires jdk.unsupported
in your module-info. This is the unfortunate nature of JPMS runtime "security". The manifold sample project provides a module-info for reference. It demonstrates common requires
statements for use with various manifold libraries, including jdk.unsupported.
module manifold.sample.project {
requires manifold.util;
requires manifold.rt;
requires manifold.ext.rt;
requires manifold.props.rt;
requires manifold.delegation.rt;
requires manifold.tuple.rt;
requires manifold.graphql.rt;
requires manifold.json.rt;
requires manifold.xml.rt;
requires manifold.yaml.rt;
requires manifold.csv.rt;
requires manifold.js.rt;
requires manifold.templates.rt;
requires manifold.science;
requires manifold.collections;
requires java.desktop;
requires jdk.unsupported;
// Register the sample Date proxy factory service implementation
// (note the META-INF/services registration is still necessary for Java 8 and Java 9+ unnamed-module)
provides manifold.ext.rt.api.IProxyFactory
with Date_To_ChronoLocalDateTime;
}
LWJGL3 makes use of Unsafe and has a module-info viamulti release jars, which completely prevents this issue.
Can you elaborate?
Multi-release jars are a Java 9 feature that allows a single jar file to have code for multiple versions of the Java runtime.
You set the attribute Multi-Release
to true
in the manifest and put classes for different Java versions in META-INF/versions/n
, where n
is the major Java version starting with 9. Since Java 8 and earlier don't support this they completely ignore this directory and manifest attribute.
Let's say you have a multi-release jar file that looks something like this:
META-INF/
- MANIFEST.MF
- versions/
- - 9/example/
- - - Example.class
- - 10/example/
- - - Example.class
example/
- Example.class
Where the root example.Example
contains the following:
package example;
public final class Example {
public static void main(String[] args) {
System.out.println("Java 8");
}
}
and the Java 9 example.Example
contains the following:
package example;
public final class Example {
public static void main(String[] args) {
System.out.println("Java " + Runtime.version().major());
}
}
and finally the Java 10+ example.Example
contains:
package example;
public final class Example {
public static void main(String[] args) {
System.out.println("Java " + Runtime.version().feature());
}
}
On Java 8 the class in the root will be used automaticly, on Java 9 the one in versions/9
will be used and in Java 10+ the one in versions/10
will be used. There are a few rules to be mindful of, but for the purposes of adding a module-info
file they don't particularly matter.
With the LWJGL3 example they have the module-info file located at META-INF/versions/9/module-info.class
, they also use this to enable faster code paths enabled by newer Java releases without having branches or using reflection.
Thanks. I’m aware of multi release jars. Are you suggesting manifold would not need Unsafe with this feature? If so, that’s not really the case. The Java.base and jdk modules still need to be opened dynamically etc. for other purposes. And Unsafe is still used for other stuff. And for manifold, multi release jars feature doesn’t really work out well. I’d use it if it worked for my use case. I appreciate the suggestion though, thanks.
Describe the bug During runtime of a project that uses Manifold a NPE is thrown from internal Manifold code that is injected into my project's classes. Making a module depend on
jdk.unsupported
or adding the VM options--add-module jdk.unsupported
causes the NPE to go away.To Reproduce Steps to reproduce the behavior:
NecessaryEvilUtil
failing to loads.m.Unsafe
Expected behavior The Manifold runtime should not be throwing a NPE
Screenshots If applicable, add screenshots to help explain your problem (drag/drop them here).
Desktop (please complete the following information):
Additional context I'm wondering if providing a real
module-info
via multi-release jars is required on newer Java versions. It may also be a good idea to modifyNecessaryEvilUtil.getUnsafe
to propagate the exception that is caught.Stack trace