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.class
auf 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-Name
xxx-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.
transitive
static
transitive
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
--output
Die 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