问题
I worked through a simple example using Project Jigsaw in Java 11.0.1, built using the oracle JDK 11 on Ubuntu 18.04.
Following that example, I have created a simple project which compiles to a module, packages the module into a jar, and then uses jlink
to create a standalone distribution. Everything works -- the end result is a smallish folder with a stripped down JRE and my module.
The project is made of only three files and some folders:
.:
build.sh src
./src:
com module-info.java
./src/com:
greetings
./src/com/greetings:
Main.java
src/com/greetings/Main.java
package com.greetings;
public class Main {
public static void main(String[] args) {
System.out.println("Greetings!");
}
}
src/module-info.java
module com.greetings { }
build.sh
#/bin/bash
#clean up from last build
rm -rf greetingsapp mlib mods
#compile
javac -d mods/com.greetings src/module-info.java src/com/greetings/Main.java
#Make module jar
mkdir mlib
jar --create --file=mlib/com.greetings.jar --main-class=com.greetings.Main -C mods/com.greetings .
#build distribution
jlink --module-path /usr/lib/jvm/java-11-oracle/jmods/:mlib --add-modules com.greetings --output greetingsapp --strip-debug --no-header-files --no-man-pages --launcher greetings=com.greetings
#run
greetingsapp/bin/greetings
All of that works. Now here's the problem:
The next thing I want to do is use an external library, so I added a few lines to Main.java:
Main.java - Updated
package com.greetings;
import org.apache.commons.cli.CommandLine; //new line
public class Main {
CommandLine line; //new line
public static void main(String[] args) {
System.out.println("Greetings!");
}
}
I then placed commons-cli-1.4.jar in a new directory named lib
.
Which created this file structure:
.:
build.sh lib src
./lib:
commons-cli-1.4.jar
./src:
com module-info.java
./src/com:
greetings
./src/com/greetings:
Main.java
I modified the compile line to include the commons jar in the classpath:
javac -cp lib/commons-cli-1.4.jar:. \
-d mods/com.greetings \
src/module-info.java src/com/greetings/Main.java
However, when I try to compile it, I get this error:
src/com/greetings/Main.java:10: error: package org.apache.commons.cli is not visible
import org.apache.commons.cli.CommandLine;
^
(package org.apache.commons.cli is declared in the unnamed module, but module org.apache.commons.cli does not read it)
1 error
How do I modify my project so I can compile against commons-cli-1.4.jar?
Edit, at the suggestion of the user nullpointer, I tried changing the -cp flag to just a -p flag, so the external jar is added to the module path instead. Unfortunately, that also doesn't work. Here are the various javac command I tried that also do not work:
javac -p lib -d mods/com.greetings \
src/module-info.java src/com/greetings/Main.java
javac --module-path=lib -d mods/com.greetings \
src/module-info.java src/com/greetings/Main.java
javac -p lib/commons-cli-1.4.jar -d mods/com.greetings \
src/module-info.java src/com/greetings/Main.java
回答1:
You've placed the jar on the classpath because of which it results into an unnamed module..
The unnamed module exports all of its packages. ...
It does not, however, mean that code in a named module can access types in the unnamed module. ...
This restriction is intentional, since allowing named modules to depend upon the arbitrary content of the class path would make reliable configuration impossible.
Instead try placing the same jar on the modulepath from where it can be inferred as an automatic module.
You would also need to ensure that the module declaration of your module is updated accordingly to define a dependence on the newly added module to access its exported packages.
module com.greetings {
requires commons.cli;
}
Edit: Trying out the complete build.sh in your case would still fail, but at the linking step, because of the presence of an automatic module.
来源:https://stackoverflow.com/questions/53246066/compile-module-that-depends-on-an-external-jar