Eine Notiz aus dem Studium von Java 9 Project Jigsaw.
OS Windows 10
Java
>java --version
java 9
Java(TM) SE Runtime Environment (build 9+181)
Java HotSpot(TM) 64-Bit Server VM (build 9+181, mixed mode)
Hello World
|-main/
| |-class/
| `-src/
| |-module-info.java
| `-sample/main/
| `-Main.java
|
`-sub/
|-class/
`-src/
|-module-info.java
`-sample/sub/
|-api/
| `-Foo.java
|-internal/
| `-FooImpl.java
|
`-FooFactory.java
sub/src/sample/sub/api/Foo.java
package sample.sub.api;
public interface Foo {
void hello();
}
sub/src/sample/sub/internal/FooImpl.java
package sample.sub.internal;
import sample.sub.api.Foo;
public class FooImpl implements Foo {
@Override
public void hello() {
System.out.println("FooImpl.hello()");
}
}
sub/src/sample/sub/FooFactory.java
package sample.sub;
import sample.sub.api.Foo;
import sample.sub.internal.FooImpl;
public class FooFactory {
public static Foo newInstance() {
return new FooImpl();
}
}
sub/src/module-info.java
module sample_module.sub {
exports sample.sub;
exports sample.sub.api;
}
main/src/sample/main/Main.java
package sample.main;
import sample.sub.FooFactory;
import sample.sub.api.Foo;
public class Main {
public static void main(String... args) {
Foo foo = FooFactory.newInstance();
foo.hello();
}
}
main/src/module-info.java
module sample_module.main {
requires sample_module.sub;
}
#Kompilieren Sie das Untermodul
> javac -d sub\class sub\src\module-info.java sub\src\sample\sub\FooFactory.java sub\src\sample\sub\api\Foo.java sub\src\sample\sub\internal\FooImpl.java
#Kompilieren Sie das Hauptmodul
> javac -p sub\class -d main\class main\src\module-info.java main\src\sample\main\Main.java
> java -p main\class;sub\class -m sample_module.main/sample.main.Main
FooImpl.hello()
sub/src/module-info.java
module sample_module.sub {
exports sample.sub;
exports sample.sub.api;
}
--Deklarieren Sie das Modul in einer speziellen Datei namens "module-info.java", die im Root-Paket abgelegt ist.
module-info.java festgelegt
--Die Moduldeklaration wird im Format Modul <Modulname> {<Moduldefinition>} beschrieben. wie der Paketname getrennt wird.{} schreiben
--exports gibt Pakete an, die der Außenwelt zugänglich gemacht werden sollensample.internal ist als interne API gedacht, daher versuche ich, sie nicht zu veröffentlichen.main/src/module-info.java
module sample_module.main {
requires sample_module.sub;
}
module-info.java sowie die Seite, auf die verwiesen wird.
--requries definiert das Modul, von dem dieses Modul abhängtsample.main) nicht ohne Exporte gestartet werden kann, aber als ich es tatsächlich ausprobiert habe, hat es funktioniert, auch wenn es nicht Exporte war.#Submodul kompilieren
> javac -d sub\class sub\src\module-info.java sub\src\sample\sub\FooFactory.java sub\src\sample\sub\api\Foo.java sub\src\sample\sub\internal\FooImpl.java
#Hauptmodul kompilieren
> javac -p sub\class -d main\class main\src\module-info.java main\src\sample\main\Main.java
--Compile verwendet weiterhin den Befehl javac
--Wenn kein abhängiges Modul vorhanden ist, können Sie mit den herkömmlichen Spezifikationen kompilieren (Submodul-Kompilierung)
module-info.java in die zu kompilierende Quelle aufzunehmen!-p (oder --module-path).-mp eingeführt, aber es scheint, dass sie sich geändert hat.> java -p main\class;sub\class -m sample_module.main/sample.main.Main
-p ( --module-path) verwendet werden soll.-m ( --module) anzugeben (bei Verwendung eines Moduls).Main.java
package sample.main;
import sample.sub.FooFactory;
import sample.sub.api.Foo;
import sample.sub.internal.FooImpl;
public class Main {
public static void main(String... args) {
FooImpl foo = (FooImpl)FooFactory.newInstance();
foo.hello();
}
}
Fehler beim Kompilieren
> javac -p sub\class -d main\class main\src\module-info.java main\src\sample\main\Main.java
main\src\sample\main\Main.java:5:Error:Paketprobe.sub.intern kann nicht angezeigt werden
import sample.sub.internal.FooImpl;
^
(Paketprobe.sub.intern ist das Modulbeispiel_module.In Sub deklariert, aber nicht exportiert)
1 Fehler
Auf diese Weise können Sie nicht auf Pakete verweisen, die nicht "exportiert" wurden.
Versuchen Sie es mit dem Hello World-Programm, indem Sie sowohl Haupt- als auch Nebenprogramm in ein Glas packen.
Gleich bis zum Kompilieren mit javac.
#Erstellen Sie ein Glas für das Untermodul
> jar -c -f sub\jar\sub-module.jar -C sub\class .
#Erstellen Sie ein Glas für das Hauptmodul
> jar -c -f main\jar\main-module.jar -C main\class .
--Verwenden Sie den Befehl jar wie zuvor, um die Modul-JAR-Datei zu erstellen
---c ist ein Befehl, der bedeutet, dass ein Glas erstellt wird (kurz für --create).
-f <JAR-Ausgabezielpfad> an
-- -C <Paketverzeichnis> ., um das angegebene Verzeichnis in jar zu verpacken#Informationen zum Submodul ausgeben
> jar -d -f sub\jar\sub-module.jar
sample_module.sub jar:file:///.../sub/jar/sub-module.jar/!module-info.class
exports sample.sub
exports sample.sub.api
requires java.base mandated
contains sample.sub.internal
#Ausgabeinformationen des Hauptmoduls
> jar -d -f main\jar\main-module.jar
sample_module.main jar:file:///.../main/jar/main-module.jar/!module-info.class
requires java.base mandated
requires sample_module.sub
contains sample.main
-- -d (--describe-module) kann die Modulinformationen von jar ausgeben.
--exports ist ein öffentliches Paket
--requires ist das abhängige Modul
--java.base ist ein Modul, das das Paket java.lang enthält und immer mitgeliefert wird, auch wenn Sie es nicht angeben.
--contains ist wahrscheinlich ein privates Paket
> java -p sub\jar;main\jar -m sample_module.main/sample.main.Main
FooImpl.hello()
jar) mit -p angeben, scheint das dortige jar gelesen zu werden.Es gibt drei Haupttypen von Modulen.
named module
Ein Modul mit Definitionsinformationen (module-info.class), die vom Modulpfad ( --module-path) gelesen werden.
Wenn wir über Module sprechen, beziehen wir uns oft auf sie.
automatic module Ein Glas ohne Definitionsinformationen, das im Modulpfad gelesen wird.
Alle Pakete werden als "Exporte" behandelt. Außerdem wird der Modulname automatisch aus dem Namen der JAR-Datei vervollständigt.
Dies ist der Fall, wenn Sie eine vor Java 9 erstellte JAR-Datei mit --module-path angeben.
Ich habe keine klare Definition gefunden, aber es scheint, dass es sich um eine JAR-Datei handeln muss, da der Modulname aus dem Dateinamen vervollständigt wird. Javadoc hat auch die folgende Beschreibung, daher denke ich, dass es mindestens ein Glas sein muss.
A JAR file that does not have a module-info.class in its top-level directory defines an automatic module (Übersetzung) Jar-Dateien ohne
module-info.classauf der obersten Ebene definieren ein automatisches Modul
http://download.java.net/java/jigsaw/docs/api/java/lang/module/ModuleFinder.html#of-java.nio.file.Path...-
unnamed module
Mit dem Klassenpfad (--class-path) geladene Module.
Alle Pakete werden als "Exporte" behandelt.
Probieren Sie verschiedene Kombinationen jedes Moduls aus (benanntes Modul, automatisches Modul, unbenanntes Modul).
Wenn Sie zuerst die Ergebnisse tabellieren,

Es sieht aus wie das.
sub/src/sample/sub/Sub.java
package sample.sub;
public class Sub {
public void method() {
System.out.println("Sub.method()");
}
}
main/src/sample/main/Main.java
package sample.main;
import sample.sub.Sub;
public class Main {
public static void main(String... args) {
Sub sub = new Sub();
sub.method();
}
}
named module -> named module Hallo Welt ist das, also werde ich es weglassen.
named module -> automatic module
Ordnerstruktur
|-main/
| |-class/
| `-src/
| |-module-info.java
| `-sample/main/
| `-Main.java
|
`-sub/
|-class/
`-src/
`-sample/sub/
`-Sub.java
Submodul kompilieren
#kompilieren
> javac -d sub\class sub\src\sample\sub\Sub.java
#Glas Kreation
> jar -c -f sub\jar\no_module-sub.jar -C sub\class .
main\src\module-info.java
module sample_module.main {
requires no.module.sub;
}
require angegebenen Submoduls gibt den Namen an, der aus dem Namen der JAR-Datei vervollständigt wird.Kompilieren Sie das Hauptmodul und starten Sie es
#Hauptmodul kompilieren
> javac -p sub\jar\no_module-sub.jar -d main\class main\src\module-info.java main\src\sample\main\Main.java
#Anlaufen
> java -p sub\jar\no_module-sub.jar;main\class -m sample_module.main/sample.main.Main
Sub.method()
-p ( --module-path) und starten Sie esAutomatic-Module-Namexxx-1.1.2.jar extrahiert xxx als Modulnamen[^ A-Za-z0-9]) durch Punkte (.)..) wiederholt wird, ersetzen Sie ihn durch einen Punkt.named module -> unnamed module Ich kann es nicht scheinen.
main/src/module-info.java
module sample_module.main {
// requires no.module.sub;
}
> javac -cp sub\jar\no_module-sub.jar -d main\class main\src\module-info.java main\src\sample\main\Main.java
main\src\sample\main\Main.java:3:Error:Paketprobe.Sub existiert nicht
import sample.sub.Sub;
^
main\src\sample\main\Main.java:7:Error:Symbol kann nicht gefunden werden
Sub sub = new Sub();
^
Symbol:Klasse Sub
Ort:Klasse Main
main\src\sample\main\Main.java:7:Error:Symbol kann nicht gefunden werden
Sub sub = new Sub();
^
Symbol:Klasse Sub
Ort:Klasse Main
3 Fehler
Selbst wenn ich jar im Klassenpfad (-cp) setze, kann die Klasse nicht gelesen werden.
automatic module -> named module
Ordnerstruktur
|-main/
| |-class/
| `-src/
| `-sample/main/
| `-Main.java
|
`-sub/
|-class/
`-src/
|-module-info.java
`-sample/sub/
`-Sub.java
sub/src/module-info.java
module sample_module.sub {
exports sample.sub;
}
Submodul kompilieren
#kompilieren
> javac -d sub\class sub\src\module-info.java sub\src\sample\sub\Sub.java
#Glas Kreation
> jar -c -f sub\jar\module-sub.jar -C sub\class .
Hauptmodul kompilieren
#kompilieren
> javac -d main\class --add-modules sample_module.sub -p sub\jar\module-sub.jar main\src\sample\main\Main.java
#Glas Kreation
> jar -c -f main\jar\no_module-main.jar -C main\class .
Lauf
> java -p sub\jar\module-sub.jar;main\jar\no_module-main.jar --add-modules sample_module.sub -m no.module.main/sample.main.Main
Sub.method()
-p ( --module-path) ohne module-info.java angegeben ist.
--Aber da es kein "module-info.java" gibt, ist "sample_module.sub" nicht "erfordert" und wird möglicherweise nicht geladen (ausgedrückt als nicht im Moduldiagramm vorhanden). Sollte ich es tun?)Dies ist eine Vorstellung von Togetter of the Gods, also kann es anders sein oder auch nicht.
automatic module -> automatic module
Ordnerstruktur
|-main/
| |-class/
| `-src/
| `-sample/main/
| `-Main.java
|
`-sub/
|-class/
`-src/
`-sample/sub/
`-Sub.java
Submodul kompilieren
#kompilieren
> javac -d sub\class sub\src\sample\sub\Sub.java
#Glas Kreation
> jar -c -f sub\jar\no_module-sub.jar -C sub\class .
Hauptmodul kompilieren
#kompilieren
> javac -d main\class -p sub\jar\no_module-sub.jar --add-modules no.module.sub main\src\sample\main\Main.java
# jar
> jar -c -f main\jar\no_module-main.jar -C main\class .
Anlaufen
> java -p sub\jar\no_module-sub.jar;main\jar\no_module-main.jar --add-modules no.module.sub -m no.module.main/sample.main.Main
Sub.method()
--Dies kann auch durch Angabe von "--add-modules" ausgeführt werden.
--add-modules angegeben werden?automatic module -> unnamed module
Submodul kompilieren
#kompilieren
> javac -d sub\class sub\src\sample\sub\Sub.java
#Glas Kreation
> jar -c -f sub\jar\no_module-sub.jar -C sub\class .
Hauptmodul kompilieren
#kompilieren
> javac -d main\class -cp sub\jar\no_module-sub.jar main\src\sample\main\Main.java
# jar
> jar -c -f main\jar\no_module-main.jar -C main\class .
Lauf
> java -p main\jar\no_module-main.jar -cp sub\jar\no_module-sub.jar -m no.module.main/sample.main.Main
Sub.method()
--Kann als unbenanntes Modul behandelt werden, indem im Klassenpfad mit -cp ein Nicht-Modul-Jar gesetzt wird
unnamed module -> named module
Ordnerstruktur
|-main/
| |-class/
| `-src/
| `-sample/main/
| `-Main.java
|
`-sub/
|-class/
`-src/
|-module-info.java
`-sample/sub/
`-Sub.java
sub/src/module-info.java
module sample_module.sub {
exports sample.sub;
}
Submodul kompilieren
#kompilieren
> javac -d sub\class sub\src\module-info.java sub\src\sample\sub\Sub.java
# jar
> jar -c -f sub\jar\module-sub.jar -C sub\class .
Hauptmodul kompilieren
#kompilieren
> javac -p sub\jar\module-sub.jar --add-modules sample_module.sub -d main\class main\src\sample\main\Main.java
#Glas Kreation
> jar -c -f main\jar\no_module-main.jar -C main\class .
Lauf
> java -p sub\jar\module-sub.jar -cp main\jar\no_module-main.jar --add-modules sample_module.sub sample.main.Main
Sub.method()
-m.unnamed module -> automatic module
Ordnerstruktur
|-main/
| |-class/
| `-src/
| `-sample/main/
| `-Main.java
|
`-sub/
|-class/
`-src/
`-sample/sub/
`-Sub.java
Submodul kompilieren
#kompilieren
> javac -d sub\class sub\src\sample\sub\Sub.java
#Glas Kreation
> jar -c -f sub\jar\no_module-sub.jar -C sub\class .
Hauptmodul kompilieren
#kompilieren
> javac -p sub\jar\no_module-sub.jar -d main\class --add-modules no.module.sub main\src\sample\main\Main.java
#Glas Kreation
> jar -c -f main\jar\no_module-main.jar -C main\class .
Lauf
> java -p sub\jar\no_module-sub.jar -cp main\jar\no_module-main.jar --add-modules no.module.sub sample.main.Main
Sub.method()
--add-modules vervollständigt wird.unnamed module -> unnamed module
Submodul kompilieren
#kompilieren
> javac -d sub\class sub\src\sample\sub\Sub.java
#Glas Kreation
> jar -c -f sub\jar\no_module-sub.jar -C sub\class .
Hauptmodul kompilieren
#kompilieren
> javac -d main\class -cp sub\jar\no_module-sub.jar main\src\sample\main\Main.java
#Glas Kreation
> jar -c -f main\jar\no_module-main.jar -C main\class .
Lauf
> java -cp sub\jar\no_module-sub.jar;main\jar\no_module-main.jar sample.main.Main
Sub.method()
――Dies ist im Grunde eine modulfreie Methode, dh sie befindet sich im selben Zustand wie das normale Kompilieren und Ausführen unter Java 8 oder weniger.
Einer der folgenden zwei Modifikatoren kann in "erfordert" eingestellt werden.
transitivestatictransitive
Modulabhängigkeiten
A -> B -> C
Angenommen, ein Modul B hängt von C ab.
Es ist dieses "transitive" Qualifikationsmerkmal, das es "C" ermöglicht, automatisch "Anforderungen" zu stellen, wenn ein anderes Modul "A" "B" mit "Anforderungen" liest.
Ordnerstruktur
|-A/
| `-src/
| |-module-info.java
| `-a/
| `-A.java
|-B/
| `-src/
| |-module-info.java
| `-b/
| `-B.java
`-C/
`-src/
|-module-info.java
`-c/
`-C.java
** C-Modul **
C.java
package c;
public class C {}
C/src/module-info.java
module module_c {
exports c;
}
** B-Modul **
B.java
package b;
import c.C;
public class B {}
B/src/module-info.java
module module_b {
requires module_c;
exports b;
}
** Ein Modul **
A.java
package a;
import b.B;
import c.C;
public class A {}
A/src/module-info.java
module module_a {
requires module_b;
// requires module_c;Versuchen Sie es ohne C-Modul
exports a;
}
kompilieren
#C-Modul kompilieren
> javac -d c\class C\src\module-info.java C\src\c\C.java
#B-Modul kompilieren
> javac -p c\class -d b\class B\src\module-info.java B\src\b\B.java
#Ein Modul kompilieren
> javac -p c\class;b\class -d a\class A\src\module-info.java A\src\a\A.java
A\src\a\A.java:4:Error:Paket c kann nicht angezeigt werden
import c.C;
^
(Paket c ist das Modulmodul_In c deklariert, aber Modulmodul_Nicht geladen in a)
1 Fehler
Das Paket "c" kann nicht referenziert werden, da das A-Modul das C-Modul nicht explizit benötigt.
B\src\module-info.java
module module_b {
requires transitive module_c;
exports b;
}
#B-Modul kompilieren
> javac -p c\class -d b\class B\src\module-info.java B\src\b\B.java
#Ein Modul kompilieren
> javac -p c\class;b\class -d a\class A\src\module-info.java A\src\a\A.java
static Verwenden Sie "static" für Module, die "zur Kompilierungszeit erforderlich, zur Laufzeit jedoch optional" sind.
Ordnerstruktur
|-main/
| `-src/
| |-module-info.java
| `-sample/main/
| |-SubFactory.java
| `-Main.java
`-sub/
`-src/
|-module-info.java
`-sample/sub/
`-Sub.java
Sub.java
package sample.sub;
public class Sub {}
sub\src\module-info.java
module sample_module.sub {
exports sample.sub;
}
SubFactory.java
package sample.main;
import sample.sub.Sub;
public class SubFactory {
public static Sub newSub() {
return new Sub();
}
}
Main.java
package sample.main;
public class Main {
public static void main(String... args) {
System.out.println("Hello World!!");
}
}
main/src/module-info.java
module sample_module.main {
requires sample_module.sub;
}
Versuchen Sie zu kompilieren.
kompilieren
#Submodul kompilieren
> javac -d sub\class sub\src\module-info.java sub\src\sample\sub\Sub.java
#Hauptmodul kompilieren
> javac -p sub\class -d main\class main\src\module-info.java main\src\sample\main\Main.java main\src\sample\main\SubFactory.java
Die Zusammenstellung besteht. Versuchen Sie es dann.
> java -p main\class -m sample_module.main/sample.main.Main
Error occurred during initialization of boot layer
java.lang.module.FindException: Module sample_module.sub not found, required by sample_module.main
Ein Fehler ist aufgetreten, weil das Submodul nicht gefunden wurde.
main\src\module-info.java
module sample_module.main {
requires static sample_module.sub;
}
Fügen Sie static hinzu und kompilieren Sie und führen Sie es auf die gleiche Weise aus.
#Hauptmodul kompilieren
> javac -p sub\class -d main\class main\src\module-info.java main\src\sample\main\Main.java main\src\sample\main\SubFactory.java
#Lauf
> java -p main\class -m sample_module.main/sample.main.Main
Hello World!!
Ich konnte es ausführen.
open Es kann nicht zur Kompilierungszeit referenziert werden, aber es kann so gesteuert werden, dass es zur Laufzeit referenziert werden kann. Dies wird verwendet, wenn Sie den Code mithilfe von Reflection referenzieren.
Es gibt zwei Typen, "opens", die für jedes Paket festgelegt sind, und "open module", die für das gesamte Modul festgelegt sind.
opens
Ordnerstruktur
|-main/
| `-src/
| |-module-info.java
| `-sample/main/
| `-Main.java
`-sub/
`-src/
|-module-info.java
`-sample/sub/
`-Sub.java
Sub.java
package sample.sub;
public class Sub {
public void sub() {
System.out.println("Sub.sub()");
}
}
sub\src\module-info.java
module sample_module.sub {
//Erstellen Sie es zunächst, ohne es überhaupt zu veröffentlichen
}
Main.java
package sample.main;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
public class Main {
public static void main(String... args) throws Exception {
Class<?> subClass = Class.forName("sample.sub.Sub");
Constructor<?> constructor = subClass.getConstructor();
Object sub = constructor.newInstance();
Method method = subClass.getMethod("sub");
method.invoke(sub);
}
}
Auf das Paket "sample.sub" wird nicht direkt verwiesen, und die Methode "Sub.sub ()" wird unter Verwendung von Reflection ausgeführt.
main/src/module-info.java
module sample_module.main {
requires sample_module.sub;
}
Versuchen Sie zu kompilieren.
#Submodul kompilieren
> javac -d sub\class sub\src\module-info.java sub\src\sample\sub\Sub.java
#Hauptmodul kompilieren
> javac -p sub\class -d main\class main\src\module-info.java main\src\sample\main\Main.java
sample.sub wird nicht statisch referenziert, daher wird es kompiliert.
Aber wenn du das tust.
> java -p sub\class;main\class -m sample_module.main/sample.main.Main
Exception in thread "main" java.lang.IllegalAccessException: class sample.main.Main (in module sample_module.main) cannot access class sample.sub.Sub (in module sample_module.sub) because module sample_module.sub does not export sample.sub to module sample_module.main
at java.base/jdk.internal.reflect.Reflection.newIllegalAccessException(Reflection.java:361)
at java.base/java.lang.reflect.AccessibleObject.checkAccess(AccessibleObject.java:589)
at java.base/java.lang.reflect.Constructor.newInstance(Constructor.java:479)
at sample_module.main/sample.main.Main.main(Main.java:10)
IllegalAccessException wird ausgelöst.
Veröffentlichen Sie sample.sub mit opens und versuchen Sie es erneut.
sub\src\module-info.java
module sample_module.sub {
opens sample.sub;
}
Kompilieren und ausführen
#Submodul kompilieren
> javac -d sub\class sub\src\module-info.java sub\src\sample\sub\Sub.java
#Hauptmodul kompilieren
> javac -p sub\class -d main\class main\src\module-info.java main\src\sample\main\Main.java
#Lauf
> java -p sub\class;main\class -m sample_module.main/sample.main.Main
Sub.sub()
Diesmal hat es gut funktioniert.
Übrigens, wenn Sie in diesem Zustand auf das sample.sub -Paket in Main.java verweisen (opens sample.sub;), ist dies wie folgt.
Main.java
package sample.main;
import sample.sub.Sub;
public class Main {
public static void main(String... args) throws Exception {
new Sub().sub();
}
}
Normalerweise ist "Sub" "neu", um die Methode auszuführen.
kompilieren
#Hauptmodul kompilieren
> javac -p sub\class -d main\class main\src\module-info.java main\src\sample\main\Main.java
main\src\sample\main\Main.java:3:Error:Paketprobe.sub kann nicht angezeigt werden
import sample.sub.Sub;
^
(Paketprobe.sub ist das Modulbeispiel_module.In Sub deklariert, aber nicht exportiert)
1 Fehler
Das Paket "sample.sub" wird nur "geöffnet", nicht "exportiert". Wenn Sie daher versuchen, beim Kompilieren statisch darauf zu verweisen, tritt ein Fehler auf.
Um die Verfügbarkeit der Referenz zu jedem Zeitpunkt zusammenzufassen,
| Referenzzeitpunkt | opens |
exports |
|---|---|---|
| Zur Kompilierungszeit | × | ○ |
| Laufzeit | ○ | ○ |
So was.
open module
opens ist eine Einstellung für ein bestimmtes Paket. Wenn Sie jedoch open module angeben, wird opens auf das gesamte Modul angewendet.
Ordnerstruktur
|-main/
| `-src/
| |-module-info.java
| `-sample/main/
| `-Main.java
`-sub/
`-src/
|-module-info.java
`-sample/sub/
|-foo/
| `-Foo.java
`-Sub.java
Foo.java
package sample.sub.foo;
public class Foo {
public void foo() {
System.out.println("Foo.foo()");
}
}
sub/src/module-info.java
open module sample_module.sub {
exports sample.sub;
}
open vor dem ModulSub.java hat sich nicht geändertMain.java
package sample.main;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
import sample.sub.Sub;
public class Main {
public static void main(String... args) throws Exception {
new Sub().sub();
Class<?> clazz = Class.forName("sample.sub.foo.Foo");
Constructor<?> constructor = clazz.getConstructor();
Object obj = constructor.newInstance();
Method method = clazz.getMethod("foo");
method.invoke(obj);
}
}
Sub Klasse wird statisch referenziert, um die Methode auszuführenFoo Klasse verwendet Reflektion, um Methoden auszuführenKompilieren und ausführen
#Submodul kompilieren
> javac -d sub\class sub\src\module-info.java sub\src\sample\sub\Sub.java sub\src\sample\sub\foo\Foo.java
#Hauptmodul kompilieren
> javac -p sub\class -d main\class main\src\module-info.java main\src\sample\main\Main.java
#Lauf
> java -p sub\class;main\class -m sample_module.main/sample.main.Main
Sub.sub()
Foo.foo()
--sample.foo.Foo hat nicht opens oder export deklariert, kann aber aus der Reflexion referenziert werden.
use, provides
ServiceLoader kann in module-info.java von Java 9 aus definiert werden.
Ordnerstruktur
|-user/
| `-src/
| |-module-info.java
| `-sample/user/
| `-Main.java
|
`-provider/
`-src/
|-module-info.java
`-sample/provider/
|-api/
| `-Foo.java
`-impl/
`-FooImpl.java
Foo.java
package sample.provider.api;
public interface Foo {
void foo();
}
FooImpl.java
package sample.provider.impl;
import sample.provider.api.Foo;
public class FooImpl implements Foo {
@Override
public void foo() {
System.out.println("FooImpl.foo()");
}
}
provider/src/module-info.java
module sample_module.provider {
exports sample.provider.api;
provides sample.provider.api.Foo with sample.provider.impl.FooImpl;
}
Main.java
package sample.user;
import java.util.ServiceLoader;
import sample.provider.api.Foo;
public class Main {
public static void main(String... args) {
for (Foo foo : ServiceLoader.load(Foo.class)) {
foo.foo();
}
}
}
user/src/module-info.java
module sample_module.user {
requires sample_module.provider;
uses sample.provider.api.Foo;
}
kompilieren
#Kompilieren des Provider-Moduls
> javac -d provider\class provider\src\module-info.java provider\src\sample\provider\api\Foo.java provider\src\sample\provider\impl\FooImpl.java
#Kompilieren des Benutzermoduls
> javac -d user\class -p provider\class user\src\module-info.java user\src\sample\user\Main.java
Lauf
> java -p provider\class;user\class -m sample_module.user/sample.user.Main
FooImpl.foo()
provider/src/module-info.java
module sample_module.provider {
exports sample.provider.api;
provides sample.provider.api.Foo with sample.provider.impl.FooImpl;
}
user/src/module-info.java
module sample_module.user {
requires sample_module.provider;
uses sample.provider.api.Foo;
}
Bietet <Dienst> mit <Dienstanbieter>;verwendet <service>;Es scheint, dass Sie sich bewusst sein sollten, dass es mehr Deklarationsmethoden gibt, beispielsweise beim Lesen des Codes des OSS-Frameworks.
[^ 1]: Klasse, die "Service" implementiert [^ 2]: Schnittstellen, abstrakte Klassen usw.
jlink Mit dem Befehl jlink können Sie eine Java-Laufzeit (Teilmenge) erstellen, die nur das Minimum an Modulen enthält. Auch wenn JRE nicht im Verteilungsziel installiert ist, können Sie die Anwendung starten, indem Sie die von jlink erstellte Teilmenge einschließen.
Ordnerstruktur
`-src/
|-module-info.java
`-sample/jlink/
`-Main.java
Main.java
package sample.jlink;
public class Main {
public static void main(String... args) {
System.out.println("Hello jlink!!");
}
}
module-info.java
module sample_module.jlink {
}
#kompilieren
> javac -d class src\module-info.java src\sample\jlink\Main.java
#Glas Kreation
> jar -c -f jar\module-jlink.jar -C class .
#Erstellen Sie eine Laufzeit mit jlink
> jlink -p .\jar;%JAVA_HOME%\jmods --add-modules sample_module.jlink --output .\output
jlink mindestens Folgendes an
-p (--module-path)--add-modules--outputDie Anwendung mit Laufzeit wird wie unten gezeigt im Ordner "output" ausgegeben.
`-output/
|-bin/
|-conf/
|-include/
|-legal/
|-lib/
`-release
Unter "bin" befindet sich die Datei "java.exe", bei der es sich um den Befehl "java" für die Teilmenge handelt.
#Gehen Sie zum Teilmengenfach
> cd output\bin
#Überprüfen Sie die mitgelieferten Module
> java --list-modules
java.base@9
sample_module.jlink
Die Teilmenge enthält nur die minimal erforderlichen Module (java.base und sample_module.jlink).
Versuchen Sie, das Programm zu starten.
> java -m sample_module.jlink/sample.jlink.Main
Hello jlink!!
sample_module.jlink ist in die Laufzeit integriert, sodass Sie es nicht mit -p angeben müssen.
Die Größe der erstellten Laufzeit betrug übrigens 35,9 MB, als ich sie mit Windows Explorer überprüfte.
Kann optional bis zu einem gewissen Grad komprimiert werden.
> jlink --compress=2 -p .\jar;%JAVA_HOME%\jmods --add-modules sample_module.jlink --output .\output
--Komprimierung kann mit --compress = N angegeben werden.
-c, --compress=<0|1|2> Enable compression of resources:
Level 0: No compression
Level 1: Constant string sharing
Level 2: ZIP
Die Notwendigkeit, die Hauptklasse beim Start mit "-m" anzugeben, ist nicht sehr gut, wenn sie an Personen verteilt wird, die mit Java nicht vertraut sind. In diesem Fall ist es praktisch, eine Skriptdatei für den Start zu generieren.
> jlink --launcher jlink-hello=sample_module.jlink/sample.jlink.Main -p .\jar;%JAVA_HOME%\jmods --add-modules sample_module.jlink --output .\output
<Befehlsname> angegebene Startskript wird unter output \ bin ausgegeben. Wenn Sie es also ausführen, wird das Programm gestartet.#Gehen Sie unter bin
> cd output\bin
#Führen Sie das Startskript aus
> jlink-hello.bat
Hello jlink!!
Die generierte Skriptdatei enthält den folgenden Inhalt.
jlink-hello.bat
@echo off
set JLINK_VM_OPTIONS=
set DIR=%~dp0
"%DIR%\java" %JLINK_VM_OPTIONS% -m sample_module.jlink/sample.jlink.Main %*
Das Shell-Skript für Linux wurde ebenfalls ausgegeben, aber kann es gestartet werden?
Mit dem Befehl jdeps können Sie herausfinden, von welchem Modul die JAR-Datei abhängt.
Wenn Sie ein vorhandenes Nicht-Modul-JAR hinzufügen, wissen Sie, welches Modul in der Standardbibliothek hinzugefügt werden soll.
Schauen Sie sich als Test Apache Commons lang-3 an.
> jdeps -s commons-lang3-3.6.jar
commons-lang3-3.6.jar -> java.base
commons-lang3-3.6.jar -> java.desktop
Wenn Sie das Glas mit der Option "-s" füttern, werden die abhängigen Module angezeigt.
java.desktop ist ein Modul, das awt und Swing enthält, aber es gibt Beans und so weiter. Aha.
Wenn es sich bei der JAR um ein benanntes Modul handelt, müssen Sie das abhängige Modul mit "--module-path" angeben (natürlich ist es seltsam, ein abhängiges Modul zu haben, um das abhängige Modul nachzuschlagen. Machen).
Recommended Posts