问题
My Java library should be compatible with Java 8 and Java 9. For running with Java 9 we need some of the Java 9 modules.
I know that I can add it via command line with --add-modules
. But it is a library and I can't control the command line.
Is there an equivalent of --add-modules
in MANIFEST.MF
? Or is there any other solution that is compatible with Java 8?
回答1:
Unfortunately, there is no equivalent of --add-modules
in MANIFEST.MF
. However, you can create module-info.java
and declare your dependency there:
module <module-name> {
requires <dependency>;
...
}
However, if you compile module-info.java
and simply put module-info.class
to your JAR, it may not work on some platforms (e.g. Android). So what to do? There is a new feature in Java 9: multi-release JAR files (JEP 238). The idea is that you can put Java 9 class files to a special directory (META-INF/version/9/
) and Java 9 will properly handle them (while Java 8 will ignore them).
So, these are the steps that you should perform:
- Compile all classes except
module-info.java
withjavac --release 8
- Compile
module-info.java
withjavac --release 9
. - Build a JAR file so it will have the following structure:
JAR root
- A.class
- B.class
- C.class
...
- META-INF
- versions
- 9
- module-info.class
The resulting JAR should be compatible with Java 8 and Java 9.
Also, you can just put module-info.class
to the META-INF
folder. This will have the same effect. This, however, may not work for some tools and platforms. So I think the first way is more preferable.
回答2:
Modules express dependencies in their module declaration, so you have to create a module-info.java
, define your module's name, dependencies (in your case with requires java.activation
and requires java.xml.bind
) and exports (more on that later).
The module declaration must be compiled by a Java 9 compiler to create a module descriptor module-info.class
that belongs into the JAR's root folder.
Java 8 and 9
Java versions prior to 9 will ignore the module-info.class
, which means if you compile the rest of your code for Java 8 (either by using javac 8
or by using the new --release
flag on javac 9
), your library still functions on that version.
Will it solve your problem?
Even Java 9 will only process your JAR as a module if it ends up on the module path. Only then will it see the requires
clauses and include the Java EE modules you are using in the module graph. This means client using your library on Java 9's class path will still have to manually add the two modules via command line.
Full modularization
If your module is used on the module path, the accessibility rules make sure that:
- your clients can only use public types in packages you exported (at compile and at run time)
- your code only sees modules you depend on
This means:
- you must include exports in your module declaration
- you must declare all dependencies, not just on the two JDK modules
Particularly the second point can be tough if you depend on projects that are not yet modularized but that's another question. 😉
回答3:
Can be that there will be the needed manifest parameters in the last minutes of Jigsaw. The disadvantages, it will only work for the main jar file.
Sample:
Add-Exports: java.base/java.lang java.base/java.lang.invoke
or
Add-Exports-Private: java.base/java.lang java.base/java.lang.invoke
http://openjdk.java.net/projects/jigsaw/spec/issues/#AddExportsInManifest http://mail.openjdk.java.net/pipermail/jpms-spec-experts/2016-September/000391.html
来源:https://stackoverflow.com/questions/43606502/can-i-require-java-9-module-via-manifest-mf