The official document: docs.oracle.com/javase/9/in…
About java9 new features, the original official: docs.oracle.com/javase/9/wh…
This thing is a list, the exact technical details need to be dug up according to the official documentation.
Modular – system of modules
The modularity of java9 comes from a separate open source project called Jigsaw.
The project website: openjdk.java.net/projects/ji…
Why modularity
As Java developers know, there is a problem with developing applications in Java: Jar Hell, which is like DLL Hell in Windows.
Let’s say we start a small application that relies on a lot of JARS, as shown below:
Excerpted from: Mark Reinhold’s talk www.youtube.com/watch?v=l1s…
This is very common. While you could make the command line smaller by using “java-djava.ext.dirs =lib XXX”, there’s no denying that his classpath is that long. By the way, extdirs is no longer allowed in java9.
On the other hand, the JDK itself has a number of apis:
It’s too big for some small devices.
helloworld
I’m going to start with helloWorld. Before doing this, check your Java version:
java -version
java version "9"
Java(TM) SE Runtime Environment (build 9+181)
Java HotSpot(TM) 64-Bit Server VM (build 9+181, mixed mode)
Copy the code
If it is not java9, but 1.8, 1.7, then go slowly do not send.
Create the main class
Let’s start by creating a Java class called Demo.
File is saved as: SRC/com/pollyduan/modular/Demo. Java
package com.pollyduan.modular; public class Demo{ public static void main(String[] args){ System.out.println("hello modular."); }}Copy the code
Compile:
├── ── ── ── ── ── ── ── ── ── ── ── ── ── ── ── ── ── ── ── ── ── ── ── ── ── ── ── ── ── ── ── ── ── ── ── ── ── ── ── ── ── ── ── ── ── ── ├ ── unregulated, unregulated, unregulated, unregulated, unregulatedCopy the code
Package the JAR and execute
$ mkdir lib
$ jar cvf lib/demo.jar -C classes .
$ java --class-path lib/demo.jar com.pollyduan.modular.Demo
hello modular.
Copy the code
— Class-path switch can be abbreviated:
$ java -cp lib/demo.jar com.pollyduan.modular.Demo
Copy the code
Of course we can specify the main class for the JAR to simplify running:
Main-Class: com.pollyduan.modular.Demo
Copy the code
You need to add the above line to manifest.mf to run it directly:
$ java -jar lib/demo.jar
Copy the code
Create a module
src/module-info.java
module hello{}
Copy the code
We write an empty module called Hello.
Compile the module
$ javac -d classes src/**.java
Copy the code
Decompile to see:
$ javap classes/module-info.class
Compiled from "module-info.java"
module hello {
requires java.base;
}
Copy the code
Why did we write an empty module and decompile an extra line? Don’t worry about that. I’ll explain why later.
Packaged module
$ jar cvf lib/hello.jar -C classes .
$ jar tf lib/hello.jar
META-INF/
META-INF/MANIFEST.MF
module-info.class
com/
com/pollyduan/
com/pollyduan/modular/
com/pollyduan/modular/Demo.class
Copy the code
Run the module
$ java --module-path lib -m hello/com.pollyduan.modular.Demo
hello modular.
Copy the code
Unlike the traditional execution jar, there is no classpath, but module-path.
Similarly the command line can be abbreviated as:
java -p lib -m hello/com.pollyduan.modular.Demo
Copy the code
Can a module add main-class? The Java9 JAR provides a create switch, packaged in this way, to specify the main class for the Module:
$ jar --create --file lib/lib.jar --main-class com.pollyduan.modular.Demo -C classes .
Copy the code
Run the module again, and the command line becomes simpler.
$ java -p lib -m hello
Copy the code
Jigsaw’s design goals
Making it easier for developers to build and maintain a large library or application;
Improve the security and maintainability of the javaSE platform and JDK implementation;
Improve application performance;
On the Javase and JDK platforms, make applications smaller for deployment on smaller cells and tight cloud deployment systems.
What are the modules
To address these issues, the JDK wraps a layer on top of the package.
module -> package -> class/interface
Copy the code
What exactly is a module?
Modules are containers for packages. Applications that rely on it are called modules, and modules have names that other modules use. Module exports a specific package for use only by packages that depend on it.Copy the code
Module is a container for packages. Module only needs to export packages that the module depends on.
Create a Module
Declare a Module
cat module-info.java
module com.foo.bar{
exports com.foo.bar.alpha;
exports com.foo.bar.beta;
}
Copy the code
Like package-info.java, it is stored in a separate Java file called module-info.java.
Create the classes you want to export
For now, the contents of the class are not important. We can write an empty class, which lists only the directory structure:
$tree.. ├ ─ ─ com │ └ ─ ─ foo │ └ ─ ─ bar │ ├ ─ ─ alpha │ │ └ ─ ─ alpha. Java │ └ ─ ─ beta │ └ ─ ─ beta. Java └ ─ ─ the module - info. JavaCopy the code
Compile the module
│ ├── ├─ │ ├─ $Java module-info.java com/ ├─ │ ├─ $Java module-info.java com/ ├─ │ ├─ $Java module-info.java com/ ├─ │ ├─ $Java module-info.java com/ ├─ │ ├─ Class │ ├─ ├─ class │ ├─ class │ ├─ class │ ├─ class │ ├─ class │ ├─ class │ ├─ module-info module-info.javaCopy the code
Packaged module
The jar CVF com. Foo. Bar - 1.0. The jar.Copy the code
Check jar structure:
$jar tf com.foo.bar-1.0.jar meta-inf/meta-inf/manifest.mf module-info.class com/ com/foo/ com/foo/bar/ com/foo/bar/alpha/ com/foo/bar/alpha/Alpha.class com/foo/bar/beta/ com/foo/bar/beta/Beta.classCopy the code
Refer to the module
Now that we have the module com.foo.bar-1.0.jar, we can reference this module using the requires keyword when defining other modules.
module com.foo.app{
requires co.foo.bar;
requires java.sql;
}
module com.foo.bar{
requires com.foo.baz;
exports com.foo.bar.alpha;
exports com.foo.bar.beta;
}
module com.foo.baz{
exports com.foo.baz.mumble;
}
Copy the code
The built-in module
JDK native packages are merged into built-in modules, such as the java.base module:
module java.base{ exports java.io; exports java.lang; exports java.lang.annotation; exports java.lang.invoke; exports java.lang.module; exports java.lang.ref; exports java.lang.reflect; exports java.lang.math; exports java.lang.net; / /... }Copy the code
All applications will rely on java.base by default, just as we didn’t explicitly say “import java.lang.*;” before. The same.
“Requires java.base” : requires java.base = “requires java.base;” .
The following com.foo.app module does not need to explicitly introduce java.base:
If com.foo.bar adds a reference to the com.foo.baz module.
So, we know that com.foo.bar also implicitly introduces java.base.
In the same way, the com.foo.baz module implicitly references java.base:
Reliable configuration
Digging deeper, we know that java.sql references a number of other apis, so the following figure is not hard to understand.
The current module structure, called readable modules, provides reliable configurations.
If you reference a module that does not exist, you will also trigger xx not found, just like jar.
Compile time:
Runtime:
The type of access
If the referenced module does not export a class, it is not accessible, which is called strong encapsulation.
For example, the com.foo.bar module has an inner class BetaImpl:
So use BeatImpl in com.foo.bar’s active reference module com.foo.app as follows:
At compile time, an exception is raised:
Means: BetaImpl inaccessible because package com. Foo bar. Beta. Internal package not be exported.
Also, even if editing with an exported version succeeds and the runtime references an unexported version module:
View the built-in modules
$ jmod list $JAVA_HOME/jmods/java.base.jmod
classes/module-info.class
classes/apple/security/AppleProvider$1.class
...
classes/java/lang/Object.class
...
bin/java
bin/keytool
...
conf/security/java.policy
...
Copy the code
See more built-in modules:
$ java --list-modules java.activation@9 java.base@9 java.compiler@9 java.corba@9 java.datatransfer@9 java.desktop@9 / /... Save spaceCopy the code
The helloworld advanced
Add a module dependency from the HelloWorld base.
Let’s review the helloWorld directory structure:
$tree Module Module ├─ class │ ├─ com │ ├─ ├── modular │ │ ├─ class-module-info ├ ─ ─ lib │ ├ ─ ─ demo. The jar │ ├ ─ ─ hello.html jar └ ─ ─ the SRC ├ ─ ─ com │ └ ─ ─ pollyduan │ └ ─ ─ modular │ └ ─ ─ demo. Java └ ─ ─ module-info.javaCopy the code
Add a module service where the service directory is the same as the module directory.
$├─ ├─ com ├─ ├─ class ├─ class ├─ class ├─ class ├─ class ├─ classCopy the code
Creating a Service Class
service/src/com/pollyduan/service/HelloService.java
package com.pollyduan.service; public class HelloService{ public void sayHi(String name){ System.out.println("Hello "+name); }}Copy the code
Declare the Service module
service/src/module-info.java
module service{
exports com.pollyduan.service;
}
Copy the code
Compiling the Service module
$javac - d service/classes service/SRC/Java $* * tree service/classes/service/classes / ├ ─ ─ com │ └ ─ ─ pollyduan │ └ ─ ─ Class │ ├ ─ garbage, ├ ─ garbage, ├ ─ garbageCopy the code
Package the Service module
jar --create --file service/lib/service.jar -C service/classes/ .
Copy the code
Modify the HelloWorld module
module/src/module-info.java
module hello{
requires service;
}
Copy the code
Modify the HelloWorld main class to use methods in Service
module/src/com/pollyduan/modular/Demo.java
package com.pollyduan.modular; import com.pollyduan.service.HelloService; public class Demo{ public static void main(String[] args){ new HelloService().sayHi("java9 modular."); }}Copy the code
Recompile the package HelloWorld
$ javac -p service/lib -d module/classes module/src/**java
$ jar --create --file module/lib/hello.jar -p service/lib --main-class com.pollyduan.modular.Demo -C module/classes .
$ java -p module/lib:service/lib -m hello
Hello java9 modular.
Copy the code
Call it a day.
Module related tools
The original javac/ JavAP, etc., will not be mentioned, here are just a few new ones. More reference: docs.oracle.com/javase/9/to…
jlink
Module consolidation tool for aggregating, optimizing, and packaging a series of modules into a custom image. This is a JRE image, not a JAR.
If we only reference the java.base module, then we can optionally package when we can:
$ jlink -p $JAVA_HOME/jmods --add-modules java.base --output jre
Copy the code
The output JRE is a full working JRE, which differs greatly in size from the native JDK:
$ du -sh $JAVA_HOME jre
493M /Library/Java/JavaVirtualMachines/jdk-9.jdk/Contents/Home
35M jre
Copy the code
This way, we can pack our own modules in.
$ mkdir jmods
$ jmod create --class-path service/lib/service.jar jmods/service.jmod
$ jmod create --class-path module/lib/hello.jar jmods/module.jmod
$ jlink -p $JAVA_HOME/jmods:jmods --add-modules java.base,hello --output jre
$ cat jre/release
JAVA_VERSION="9"
MODULES="java.base service hello"
./jre/bin/java --list-modules
hello
java.base@9
service
Copy the code
Note that module-path values use the same separators as CLASspath, such as semicolons on Windows and colons on Linux; The values of the add-modules switch are comma-separated.
Thus, we have packaged a 30M JRE, and we have packaged our own Module. And then what? Direct execution module look:
$ ./jre/bin/java -m hello
Hello java9 modular.
Copy the code
Jlink also provides a launcher switch that compiles our modules into executable files, the same as Java commands, in the JRE /bin.
$ jlink -p $JAVA_HOME/jmods:jmods --add-modules java.base,hello --launcher Hello=hello --output jre
$ ls jre/bin
Hello java keytool
$ ./jre/bin/Hello
Hello java9 modular.
Copy the code
Notice the format of the launcher: “[command]=[module]”, the command is capitalized to distinguish it.
The jlink switch has many functions, including the following functions to compress the already small JRE:
$ jlink -p $JAVA_HOME/jmods:jmods --add-modules java.base,hello --launcher Hello=hello \
--compress 2 --strip-debug \
--output jre_mini
$ du -sh jre*
35M jre
21M jre_mini
Copy the code
jdeps
This is a dependency parser for Java class files.
$ jdeps --module-path service/lib module/lib/hello.jar hello [file:///Users/pollyduan/tmp/java/java9/module/lib/hello.jar] requires mandated java.base (@9) requires service hello -> java.base hello -> service com.pollyduan.modular -> com.pollyduan.service service com.pollyduan.modular -> java.lang java.baseCopy the code
jmod
Used to create JMOD files and view existing JMOD files.
Create jmod file:
$ jmod create --class-path . com.foo.bar.jmod $ jmod list com.foo.bar.jmod classes/module-info.class classes/.com.foo.bar.jmod.tmp classes/com/foo/bar/alpha/Alpha.class classes/com/foo/bar/alpha/Alpha.java Classes/com/foo/bar/beta/beta. Class classes/com/foo/bar/beta/beta. Java classes/com foo bar - 1.0. The jar classes/module-info.javaCopy the code
jdeprscan
This is a static analysis tool for the JAR, looking for the API that it depends on.
$jdeprscan dom4j-1.6.1.jar Jar file dom4j-1.6.1.jar Class org/dom4j/bean/BeanMetaData use outdated approach Java/lang/Integer: : < init > error: (I) V Can't find the org/relaxng datatype/DatatypeException error: can't find the class MSV/datatype/XSD/com/sun/XSDatatype error: Can't find the kind of com/sun/MSV/datatype/DatabindableDatatype error: can't find the kind of com/sun/MSV/datatype/SerializationContext error: Can't find the class MSV/datatype/XSD/com/sun/TypeIncubator error: Can't find the class MSV/datatype/XSD/com/sun/DatatypeFactory class org/dom4j/IO/SAXEventRecorder use outdated method of Java/lang/Integer: : < init > (I) V Class org/dom4j/IO/SAXHelper use outdated org/XML/sax/helpers/XMLReaderFactory class org/dom4j/IO/SAXReader use outdated classes Org/XML/sax/helpers/XMLReaderFactory error: can not find the org/xmlpull/v1 / XmlPullParserFactory error: Can't find the kind of org/xmlpull/v1 / XmlPullParser error: can not find the org/GJT/XPP XmlPullParserFactory error: can't find the kind of org/GJT/XPP/XmlPullParser error: Unable to find class org/jaxen/XPath error: Can't find the kind of org/jaxen VariableContext class org/dom4j/tree/NamespaceCache use outdated methods Java/lang/Integer: : < init > (I) V class Org/dom4j/tree/NamespaceCache use outdated method of Java/lang/Float: : < init > V (F) error: can't find the kind of org/jaxen/the NamespaceContext error: Can't find the kind of org/jaxen SimpleNamespaceContext error: can not find the org/jaxen/dom4j Dom4jXPath error: can't find the kind of org/jaxen JaxenException error: Can't find the kind of org/jaxen/pattern/pattern error: can not find the org/jaxen/Context error: can't find the kind of org/jaxen/pattern/PatternParser error: Can't find the org/jaxen saxpath/SAXPathException error: can not find the org/jaxen/ContextSupport error: can't find the kind of org/jaxen XPathFunctionContext error: Can't find the kind of org/jaxen SimpleVariableContext error: can not find the org/jaxen/dom4j DocumentNavigator error: can't find the kind of org/GJT/XPP/XmlStartTagCopy the code
Module summary
keywords
Java module descriptor module-info.class modular jar files Module JAR file Jmod Files Module manifest file Observable Modules readable Modules => reliable Configuration Accessible types => Strong encapsulationCopy the code
The difference between Module and JAR
A JAR is really just a collection of class files, like a ZIP document; Module, on the other hand, is a canonical Java component with more tool support than jar. Resources in the JAR can be used arbitrarily; Resources in the Module can only be used if they are exported. Module is still a JAR carrier. In a physical sense, module can be understood as a module-info.class in a JAR. ├─ bin ├─ classes ├─ SRC Project ├─ bin ├─ classes ├─ SRC ├── ── ── ── ── ── ── ── ── ── ── ── ── ── ── ── ── ── ── ── ── ── ── ─Copy the code
Module issues to be aware of
Module dependencies also have cyclic dependencies, which need attention. Module A, requires B; Module B has requires A.
Does the IDE support it? Traditional ides, which manage projects based on classpath, now need to support module-Path
Module packages jars that you can still use as normal jars, and no one is stopping you, at least for now. This is not to say that modules are completely meaningless, just as members in class files are private and not accessible externally. You can access them by reflection.
Application scenarios of modules
First, the most prominent use is to use JLink to package custom images and distribute them to run in small cells, such as Docker, embedded devices.
Second, there will surely be more and more containers to support running modules directly.
It then has a place in the hot-swappable plug-in scenario for applications.
Finally, there is the way modules run instead of jar.
Wait and see.