Une note de l'étude de 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;
}
#Compilez le sous-module
> 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
#Compilez le module principal
> 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;
}
--Déclarez le module dans un fichier spécial appelé module-info.java
placé dans le paquet racine.
--Le nom est fixé à module-info.java
--La déclaration du module est décrite au format module <nom du module> {<définition du module>}
.
comme le nom du package.sample_module.sub
différent du package. Attaché{}
--ʻExports` spécifie les paquets à exposer à l'extérieursample.sub.internal
est conçu comme une API interne, donc j'essaye de ne pas le publier.main/src/module-info.java
module sample_module.main {
requires sample_module.sub;
}
--Le côté qui fait référence à d'autres modules décrit également la déclaration du module en utilisant module-info.java
ainsi que le côté référencé.
--requries
définit le module dont dépend ce module
sample_module.sub
mentionné précédemment.sample.main
) ne peut pas être démarré sans ʻexports, mais quand je l'ai essayé, cela fonctionnait même sans ʻexports
.#Compilation du sous-module
> 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
#Compilation du module principal
> javac -p sub\class -d main\class main\src\module-info.java main\src\sample\main\Main.java
--Compile utilise toujours la commande javac
--S'il n'y a pas de modules dépendants, vous pouvez compiler avec les spécifications conventionnelles (compilation de sous-modules)
module-info.java
dans le source à compiler!
--S'il y a des modules dépendants, spécifiez le chemin du dossier où se trouvent les modules dépendants avec l'option -p
(ou --module-path
).-mp
, mais il semble qu'elle ait changé.> java -p main\class;sub\class -m sample_module.main/sample.main.Main
-p
( --module-path
).;
pour Windows et un deux-points :
pour Linux.-m
( --module
) (lors de l'utilisation d'un module).<nom du module> / <nom de la classe principale>
sample_module.main / sample.main.Main
est utilisé pour spécifier la classe sample.main.Main
du module sample_module.main
.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();
}
}
État d'erreur de compilation
> 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:Erreur:Échantillon de paquet.sub.interne ne peut pas être affiché
import sample.sub.internal.FooImpl;
^
(Échantillon de paquet.sub.interne est l'exemple de module_module.Déclaré en sous mais non exporté)
1 erreur
De cette manière, vous ne pouvez pas faire référence à des paquets qui ne sont pas des «exportations».
Essayez d'utiliser le programme Hello World en emballant à la fois le principal et le sous-jar dans un bocal.
Idem pour compiler avec javac
.
#Créer un pot pour le sous-module
> jar -c -f sub\jar\sub-module.jar -C sub\class .
#Créez un pot pour le module principal
> jar -c -f main\jar\main-module.jar -C main\class .
--Utilisez la commande jar
comme précédemment pour créer le fichier jar du module
---c
est une commande qui signifie créer un pot (abréviation de --create
)
--Spécifiez la destination de sortie avec -f <chemin de destination de sortie jar>
-- -C <répertoire du package> .
pour empaqueter le répertoire spécifié dans le fichier jar
#Informations sur le sous-module de sortie
> 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
#Informations de sortie du module principal
> 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
) peut afficher les informations de module de jar.
--ʻExports est un package public --
requires est le module dépendant --
java.base est un module qui inclut le package
java.lang, et il est toujours fourni avec lui même si vous ne le spécifiez pas. --
contains` est probablement un paquet privé
> java -p sub\jar;main\jar -m sample_module.main/sample.main.Main
FooImpl.hello()
--Si vous spécifiez le dossier avec le module (jar
) avec -p
, il semble que le fichier jar y sera lu.
Il existe trois principaux types de modules.
named module
Un module avec des informations de définition (module-info.class
) lues par le chemin du module ( --module-path
).
Lorsque nous parlons de modules, nous y faisons souvent référence.
automatic module Un fichier jar sans informations de définition lu dans le chemin du module.
Tous les paquets sont traités comme des «exportations». De plus, le nom du module est automatiquement complété à partir du nom du fichier jar.
C'est le cas si vous spécifiez un fichier jar créé avant Java 9 avec --module-path
.
Je n'ai pas trouvé de définition claire, mais il semble que ce doit être un fichier jar car le nom du module est complété à partir du nom du fichier. Javadoc a également la description suivante, donc je pense qu'il doit être au moins un pot.
A JAR file that does not have a module-info.class in its top-level directory defines an automatic module (Traduction) Les fichiers Jar qui n'ont pas
module-info.class
au niveau supérieur définissent un module automatique
http://download.java.net/java/jigsaw/docs/api/java/lang/module/ModuleFinder.html#of-java.nio.file.Path...-
unnamed module
Modules chargés avec le chemin de classe (--class-path
).
Tous les paquets sont traités comme des «exportations».
Essayez différentes combinaisons de chaque module (module nommé, module automatique, module sans nom).
Si vous comptez d'abord les résultats,
Ça ressemble à ça.
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 Hello World est ceci, donc je vais l'omettre.
named module -> automatic module
Structure des dossiers
|-main/
| |-class/
| `-src/
| |-module-info.java
| `-sample/main/
| `-Main.java
|
`-sub/
|-class/
`-src/
`-sample/sub/
`-Sub.java
Compilation du sous-module
#compiler
> javac -d sub\class sub\src\sample\sub\Sub.java
#création de pot
> 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;
}
requires
spécifie le nom qui est complété à partir du nom du fichier jar.no_module-sub.jar
, le nom du module sera no.module.sub
Compilez et lancez le module principal
#Compilation du module principal
> javac -p sub\jar\no_module-sub.jar -d main\class main\src\module-info.java main\src\sample\main\Main.java
#Commencez
> java -p sub\jar\no_module-sub.jar;main\class -m sample_module.main/sample.main.Main
Sub.method()
--Définissez le sous-module sur -p
( --module-path
) et démarrez-le
.jar
de fin- (\ d + (\. | $))
--La partie après cette expression régulière est traitée comme une chaîne de version
--xxx-1.1.2.jar
extrait xxx
comme nom de module
--Remplacer les caractères autres que les caractères alphanumériques ([^ A-Za-z0-9]
) par des points (.
)
--Si le point (.
) est répété, remplacez-le par un point.named module -> unnamed module Je n'arrive pas à le faire.
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:Erreur:Échantillon de paquet.le sous n'existe pas
import sample.sub.Sub;
^
main\src\sample\main\Main.java:7:Erreur:Impossible de trouver le symbole
Sub sub = new Sub();
^
symbole:Sous-classe
endroit:Classe principale
main\src\sample\main\Main.java:7:Erreur:Impossible de trouver le symbole
Sub sub = new Sub();
^
symbole:Sous-classe
endroit:Classe principale
3 erreurs
Même si je place jar dans le chemin de la classe (-cp
), la classe ne peut pas être lue.
automatic module -> named module
Structure des dossiers
|-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;
}
Compilation du sous-module
#compiler
> javac -d sub\class sub\src\module-info.java sub\src\sample\sub\Sub.java
#création de pot
> jar -c -f sub\jar\module-sub.jar -C sub\class .
Compiler le module principal
#compiler
> javac -d main\class --add-modules sample_module.sub -p sub\jar\module-sub.jar main\src\sample\main\Main.java
#création de pot
> jar -c -f main\jar\no_module-main.jar -C main\class .
Courir
> 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
) sans module-info.java
.
--Mais comme il n'y a pas de module-info.java
, sample_module.sub
n'est pas requiert
et n'est pas chargé, peut-être (exprimé comme non présent sur le graphique du module). Devrais-je le faire?)--add-modules
pour ajouter n'importe quel module à ce qu'on appelle un module racine.
--Je ne sais pas exactement ce qu'est le module racine, mais je pense qu'il ajoute probablement un module comme point de départ du graphe de dépendances.sample_module.sub
et vous permettra d'utiliser les classes là-bas.
--Il semble que le module automatique soit traité comme si tous les autres modules étaient "requiert", il semble donc que le module ajouté en tant que module racine puisse être référencé à partir du module automatique.--add-modules
puisse être référencé à partir du module principal (module automatique).C'est une imagination qui regarde Togetter of the Gods, donc cela peut ou non être différent.
automatic module -> automatic module
Structure des dossiers
|-main/
| |-class/
| `-src/
| `-sample/main/
| `-Main.java
|
`-sub/
|-class/
`-src/
`-sample/sub/
`-Sub.java
Compilation du sous-module
#compiler
> javac -d sub\class sub\src\sample\sub\Sub.java
#création de pot
> jar -c -f sub\jar\no_module-sub.jar -C sub\class .
Compiler le module principal
#compiler
> 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 .
Commencez
> 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()
--Cela peut également être exécuté en spécifiant --add-modules
.
--add-modules
?automatic module -> unnamed module
Compilation du sous-module
#compiler
> javac -d sub\class sub\src\sample\sub\Sub.java
#création de pot
> jar -c -f sub\jar\no_module-sub.jar -C sub\class .
Compiler le module principal
#compiler
> 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 .
Courir
> java -p main\jar\no_module-main.jar -cp sub\jar\no_module-sub.jar -m no.module.main/sample.main.Main
Sub.method()
--Peut être traité comme un module sans nom en définissant un fichier jar non-module dans le chemin de classe avec -cp
unnamed module -> named module
Structure des dossiers
|-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;
}
Compilation du sous-module
#compiler
> 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 .
Compiler le module principal
#compiler
> javac -p sub\jar\module-sub.jar --add-modules sample_module.sub -d main\class main\src\sample\main\Main.java
#création de pot
> jar -c -f main\jar\no_module-main.jar -C main\class .
Courir
> java -p sub\jar\module-sub.jar -cp main\jar\no_module-main.jar --add-modules sample_module.sub sample.main.Main
Sub.method()
--add-modules
.-m
.unnamed module -> automatic module
Structure des dossiers
|-main/
| |-class/
| `-src/
| `-sample/main/
| `-Main.java
|
`-sub/
|-class/
`-src/
`-sample/sub/
`-Sub.java
Compilation du sous-module
#compiler
> javac -d sub\class sub\src\sample\sub\Sub.java
#création de pot
> jar -c -f sub\jar\no_module-sub.jar -C sub\class .
Compiler le module principal
#compiler
> javac -p sub\jar\no_module-sub.jar -d main\class --add-modules no.module.sub main\src\sample\main\Main.java
#création de pot
> jar -c -f main\jar\no_module-main.jar -C main\class .
Courir
> 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
.unnamed module -> unnamed module
Compilation du sous-module
#compiler
> javac -d sub\class sub\src\sample\sub\Sub.java
#création de pot
> jar -c -f sub\jar\no_module-sub.jar -C sub\class .
Compiler le module principal
#compiler
> javac -d main\class -cp sub\jar\no_module-sub.jar main\src\sample\main\Main.java
#création de pot
> jar -c -f main\jar\no_module-main.jar -C main\class .
Courir
> java -cp sub\jar\no_module-sub.jar;main\jar\no_module-main.jar sample.main.Main
Sub.method()
Il s'agit essentiellement d'une méthode sans module, c'est-à-dire qu'elle est dans le même état que la compilation et l'exécution normales sous Java 8 ou moins.
L'un des deux modificateurs suivants peut être défini dans «requires».
transitive
static
transitive
Dépendances de module
A -> B -> C
Supposons qu'un module «B» dépend de «C». C'est ce qualificatif «transitif» qui permet à «C» de créer automatiquement «requires» lorsqu'un autre module «A» charge «B» avec «requires».
Structure des dossiers
|-A/
| `-src/
| |-module-info.java
| `-a/
| `-A.java
|-B/
| `-src/
| |-module-info.java
| `-b/
| `-B.java
`-C/
`-src/
|-module-info.java
`-c/
`-C.java
** module C **
C.java
package c;
public class C {}
C/src/module-info.java
module module_c {
exports c;
}
** module B **
B.java
package b;
import c.C;
public class B {}
B/src/module-info.java
module module_b {
requires module_c;
exports b;
}
** Un module **
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;Essayez sans avoir besoin du module C
exports a;
}
compiler
#Module de compilation C
> javac -d c\class C\src\module-info.java C\src\c\C.java
#Module de compilation B
> javac -p c\class -d b\class B\src\module-info.java B\src\b\B.java
#Compiler un module
> 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:Erreur:Le package c ne peut pas être affiché
import c.C;
^
(Le package c est le module module_Déclaré en c, mais module module_Non chargé dans un)
1 erreur
Le package «c» ne peut pas être référencé car le module A ne requiert pas explicitement le module C.
B\src\module-info.java
module module_b {
requires transitive module_c;
exports b;
}
transitive
au module C qui était requis
dans module-info.java
du module B.#Module de compilation B
> javac -p c\class -d b\class B\src\module-info.java B\src\b\B.java
#Compiler un module
> javac -p c\class;b\class -d a\class A\src\module-info.java A\src\a\A.java
static
Utilisez static
pour les modules qui sont" requis au moment de la compilation mais facultatifs au moment de l'exécution ".
Structure des dossiers
|-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;
}
SubFactory
qui fait référence à la classe du sous-module.Main
n'utilise pas SubFactory
, le sous-module est inutile au démarrage.Essayez de compiler.
compiler
#Compilation du sous-module
> javac -d sub\class sub\src\module-info.java sub\src\sample\sub\Sub.java
#Compilation du module principal
> javac -p sub\class -d main\class main\src\module-info.java main\src\sample\main\Main.java main\src\sample\main\SubFactory.java
La compilation passe. Ensuite, essayez de l'exécuter.
> 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
Une erreur s'est produite car le sous-module n'a pas pu être trouvé.
main\src\module-info.java
module sample_module.main {
requires static sample_module.sub;
}
Ajoutez static
et compilez et exécutez de la même manière.
#Compilation du module principal
> javac -p sub\class -d main\class main\src\module-info.java main\src\sample\main\Main.java main\src\sample\main\SubFactory.java
#Courir
> java -p main\class -m sample_module.main/sample.main.Main
Hello World!!
J'ai pu l'exécuter.
open Il ne peut pas être référencé au moment de la compilation, mais il peut être contrôlé afin qu'il puisse être référencé au moment de l'exécution. Cela sera utilisé lorsque vous référencerez le code à l'aide de la réflexion.
Il existe deux types, ʻopens, qui est défini pour chaque paquet, et ʻopen module
, qui est défini pour l'ensemble du module.
opens
Structure des dossiers
|-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 {
//Tout d'abord, créez-le sans le publier du tout
}
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);
}
}
Le package sample.sub
n'est pas directement référencé, et la méthode Sub.sub ()
est exécutée en utilisant la réflexion.
main/src/module-info.java
module sample_module.main {
requires sample_module.sub;
}
Essayez de compiler.
#Compilation du sous-module
> javac -d sub\class sub\src\module-info.java sub\src\sample\sub\Sub.java
#Compilation du module principal
> javac -p sub\class -d main\class main\src\module-info.java main\src\sample\main\Main.java
sample.sub
n'est pas référencé statiquement, il se compile donc.
Mais quand tu fais ça.
> 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` est levée.
Publiez sample.sub
avec ʻopens` et réessayez.
sub\src\module-info.java
module sample_module.sub {
opens sample.sub;
}
Compiler et exécuter
#Compilation du sous-module
> javac -d sub\class sub\src\module-info.java sub\src\sample\sub\Sub.java
#Compilation du module principal
> javac -p sub\class -d main\class main\src\module-info.java main\src\sample\main\Main.java
#Courir
> java -p sub\class;main\class -m sample_module.main/sample.main.Main
Sub.sub()
Cette fois, cela a bien fonctionné.
Au fait, si vous faites référence au package sample.sub
dans Main.java
dans cet état (ʻopens sample.sub;`), ce sera comme suit.
Main.java
package sample.main;
import sample.sub.Sub;
public class Main {
public static void main(String... args) throws Exception {
new Sub().sub();
}
}
Normalement, «Sub» est «nouveau» pour exécuter la méthode.
compiler
#Compilation du module principal
> 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:Erreur:Échantillon de paquet.le sous ne peut pas être affiché
import sample.sub.Sub;
^
(Échantillon de paquet.sub est l'exemple de module_module.Déclaré en sous mais non exporté)
1 erreur
Le package sample.sub
est simplement ʻopens, pas ʻexports
.
Par conséquent, si vous essayez d'y faire référence de manière statique au moment de la compilation, une erreur se produit.
Pour résumer la disponibilité de la référence à chaque moment,
Moment de référence | opens |
exports |
---|---|---|
Au moment de la compilation | × | ○ |
Durée | ○ | ○ |
Comme ça.
open module
ʻOpens est un paramètre pour un paquet spécifique, mais si vous spécifiez ʻopen module
, ʻopens` est appliqué à l'ensemble du module.
Structure des dossiers
|-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;
}
avant le module --Seulement
sample.sub ʻexports
, et rien n'est défini pour le package sample.sub.foo
.
--Sub.java
n'a pas changéMain.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);
}
}
--La classe Sub
est référencée statiquement pour exécuter la méthode
Foo
utilise la réflexion pour exécuter des méthodesCompiler et exécuter
#Compilation du sous-module
> javac -d sub\class sub\src\module-info.java sub\src\sample\sub\Sub.java sub\src\sample\sub\foo\Foo.java
#Compilation du module principal
> javac -p sub\class -d main\class main\src\module-info.java main\src\sample\main\Main.java
#Courir
> java -p sub\class;main\class -m sample_module.main/sample.main.Main
Sub.sub()
Foo.foo()
--sample.sub.foo.Foo
n'a pas déclaré ʻopens ou ʻexports
, mais il peut être référencé par réflexion.
module
avec ʻopen, tous les paquets contenus dans ce module seront qualifiés avec ʻopens
.use, provides
ServiceLoader peut être défini dans module-info.java
à partir de Java 9.
Structure des dossiers
|-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;
}
compiler
#Compilation du module fournisseur
> javac -d provider\class provider\src\module-info.java provider\src\sample\provider\api\Foo.java provider\src\sample\provider\impl\FooImpl.java
#Compilation du module utilisateur
> javac -d user\class -p provider\class user\src\module-info.java user\src\sample\user\Main.java
Courir
> 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;
}
provides
pour spécifier le" Service Provider "pour" Service [^ 2] ".
--fournit <service> avec <fournisseur de services>;
ServiceLoader
utilise ʻusespour spécifier le" service "à utiliser. --ʻUtilise <service>;
ServiceLoader
normalIl semble que vous devez être conscient qu'il existe plus de méthodes de déclaration, comme lors de la lecture du code du framework OSS.
[^ 1]: Classe qui implémente "service" [^ 2]: Interfaces, classes abstraites, etc.
jlink Vous pouvez utiliser la commande jlink pour créer un environnement d'exécution Java (sous-ensemble) qui ne contient que le strict minimum de modules. Même si JRE n'est pas installé dans la destination de distribution, vous pouvez démarrer l'application en incluant le sous-ensemble créé par jlink.
Structure des dossiers
`-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 {
}
#compiler
> javac -d class src\module-info.java src\sample\jlink\Main.java
#création de pot
> jar -c -f jar\module-jlink.jar -C class .
#Créer un runtime avec jlink
> jlink -p .\jar;%JAVA_HOME%\jmods --add-modules sample_module.jlink --output .\output
--Dans la commande jlink
, spécifiez au moins ce qui suit
- -p
(--module-path
)
--Spécifiez le chemin où se trouve le module à inclure
jmods
sous le dossier d'installation JDK9 (% JAVA_HOME%
) au chemin du module.
--add-modules
--Il semble spécifier le module racine
――Je ne suis pas sûr de ce qu'est le module racine, mais je pense que c'est probablement le point de départ pour créer un graphique des dépendances du module.
――Si vous spécifiez ici, je pense que les modules requis pour l'expression Imozuru seront recherchés et incorporés dans le runtime que vous créez.--output
--Spécifiez le chemin du dossier de destination de sortie
--Si le dossier existe déjà, une erreur se produira, spécifiez donc un chemin qui n'existe pas.L'application avec runtime est sortie dans le dossier ʻoutput` comme indiqué ci-dessous.
`-output/
|-bin/
|-conf/
|-include/
|-legal/
|-lib/
`-release
Sous bin
se trouve le fichier java.exe
, qui est la commande java
pour le sous-ensemble.
#Accédez à la corbeille du sous-ensemble
> cd output\bin
#Vérifiez les modules inclus
> java --list-modules
java.base@9
sample_module.jlink
Le sous-ensemble contient uniquement les modules minimum requis (java.base
et sample_module.jlink
).
Essayez de démarrer le programme.
> java -m sample_module.jlink/sample.jlink.Main
Hello jlink!!
sample_module.jlink
est intégré au runtime, vous n'avez donc pas besoin de le spécifier avec -p
.
À propos, la taille du runtime créé était de 35,9 Mo lorsque je l'ai vérifiée avec l'Explorateur Windows.
Peut être compressé dans une certaine mesure en option.
> jlink --compress=2 -p .\jar;%JAVA_HOME%\jmods --add-modules sample_module.jlink --output .\output
--Compression peut être spécifiée avec --compress = N
.
-c, --compress=<0|1|2> Enable compression of resources:
Level 0: No compression
Level 1: Constant string sharing
Level 2: ZIP
La nécessité de spécifier la classe principale avec -m
au démarrage n'est pas très bonne lors de la distribution à des personnes qui ne sont pas familiarisées avec Java.
Dans ce cas, il est pratique de générer un fichier script pour le démarrage.
> jlink --launcher jlink-hello=sample_module.jlink/sample.jlink.Main -p .\jar;%JAVA_HOME%\jmods --add-modules sample_module.jlink --output .\output
--Spécifiez --launcher <nom de la commande> = <classe principale>
<nom de la commande>
est sorti sous ʻoutput \ bin`, donc si vous l'exécutez, le programme démarrera.#Passer sous la poubelle
> cd output\bin
#Exécuter le script de démarrage
> jlink-hello.bat
Hello jlink!!
Le fichier de script généré a le contenu suivant.
jlink-hello.bat
@echo off
set JLINK_VM_OPTIONS=
set DIR=%~dp0
"%DIR%\java" %JLINK_VM_OPTIONS% -m sample_module.jlink/sample.jlink.Main %*
Le script shell pour Linux a également été produit, mais peut-il être démarré?
Vous pouvez utiliser la commande jdeps
pour savoir de quel module dépend le fichier jar.
Lorsque vous ajoutez un fichier jar non module existant, vous saurez quel module de la bibliothèque standard ajouter.
Pour tester, consultez Apache Commons lang-3.
> jdeps -s commons-lang3-3.6.jar
commons-lang3-3.6.jar -> java.base
commons-lang3-3.6.jar -> java.desktop
Le fait d'alimenter le pot avec l'option -s
vous montrera les modules dépendants.
java.desktop est un module qui inclut awt et swing, mais il y a des beans et ainsi de suite. Je vois.
Si le fichier jar est un module nommé, vous devez spécifier le module dépendant avec --module-path
(enfin, bien sûr, cela semble bizarre d'avoir un module dépendant pour rechercher le module dépendant. Faire).
Recommended Posts