SlideShare ist ein Scribd-Unternehmen logo
1 von 36
Getting started with
Java 9 modules
src/main/java
api/Foo.java
internal/Qux.java
<project>
<modelVersion>4.0.0</modelVersion>
<groupId>example</groupId>
<artifactId>foo</artifactId>
<version>1</version>
</project>
<project>
<modelVersion>4.0.0</modelVersion>
<groupId>example</groupId>
<artifactId>bar</artifactId>
<version>1</version>
</project>
src/main/java
api/Bar.java
internal/Baz.java
pom.xml pom.xml
<project>
<modelVersion>4.0.0</modelVersion>
<groupId>example</groupId>
<artifactId>bar</artifactId>
<version>1</version>
<dependencies>
<dependency>
<groupId>example</groupId>
<artifactId>foo</artifactId>
<version>1</version>
</dependency>
</dependencies>
</project>
example.foo
api/Foo.java
internal/Qux.java
example.bar
api/Bar.java
internal/Baz.java
module-info.java module-info.java
module example.foo {} module example.bar {
requires example.foo;
}
module example.foo {
exports api;
}
Scope
Task module descriptor
module descriptor
deployment descriptor
build execution descriptor
API for custom tasks
runtime
compile-time
build-time
Type declarative declarative/programmatic
Unit Java package (sub-)project
api/Foo.class internal/Qux.class api/Bar.class internal/Baz.class
api/Foo.class internal/Qux.class api/Bar.class internal/Baz.class
(system) class path
Modularity prior to Java 9 is emulated by class loader hierarchies. By tweaking class
loaders to define multiple parents, it is also possible to run several versions of the
same module (e.g. OSGi).
api/Foo.class internal/Qux.class api/Bar.class internal/Baz.class
api/Foo.class internal/Qux.class api/Bar.class internal/Baz.class
module loader
example.foo
example.bar
“example.bar reads example.foo”
The integrity of the module graph is verified by the Java 9 runtime. Jars without a
module-info.class are typically contained by the unnamed module that reads all modules.
module example.qux {
exports example.bar;
}
module example.foo {
requires example.foo;
exports api;
}
<project>
<modelVersion>4.0.0</modelVersion>
<groupId>example</groupId>
<artifactId>qux</artifactId>
<version>1</version>
</project>
<project>
<modelVersion>4.0.0</modelVersion>
<groupId>example</groupId>
<artifactId>bar</artifactId>
<version>1</version>
</project>
<project>
<modelVersion>4.0.0</modelVersion>
<groupId>example</groupId>
<artifactId>foo</artifactId>
<version>1</version>
</project>
module example.bar {
requires example.foo;
}
module example.bar {
requires transitive
example.foo;
}
Imports are non-transitive by default (what is a good default for a runtime module system).
module example.bar {
requires example.foo;
requires java.xml;
}
module java.base {
exports java.lang;
exports java.io;
exports java.util;
// ...
}
module java.xml {
exports org.xml.sax;
// ...
}
module example.foo {
exports api;
// ...
}
module example.bar {
requires example.foo;
requires java.xml;
}
<project>
<modelVersion>4.0.0</modelVersion>
<groupId>example</groupId>
<artifactId>foo</artifactId>
<version>1</version>
</project>
module java.base {
exports java.lang;
exports java.io;
exports java.util;
// ...
}
module java.xml {
exports org.xml.sax;
// ...
}
Modules can use non-modularized code as automatic modules (referenced by jar name).
Automatic modules export every package and import any module.
Automatic modules should only be used locally to avoid depending on a name.
example-foo-1.jar
module java.base {
exports java.lang;
exports java.io;
exports java.util;
// ...
}
module java.xml {
exports org.xml.sax;
// ...
}
module example.foo {
exports api;
// ...
}
<project>
<modelVersion>4.0.0</modelVersion>
<groupId>example</groupId>
<artifactId>bar</artifactId>
<version>1</version>
</project>
Non-modularized code can still run on the class path within the unnamed module.
The unnamed module imports any module but does not export any packages.
module java.base {
exports java.lang;
exports java.io;
exports java.util;
// ...
}
<project>
<modelVersion>4.0.0</modelVersion>
<groupId>example</groupId>
<artifactId>bar</artifactId>
<version>1</version>
</project>
import sun.misc.BASE64Encoder
java 
--add-exports 
java.base/sun.misc=ALL-UNNAMED
Module::addExport
Module::addRead
Instrumentation::redefineModule;
module java.base {
exports java.lang;
exports java.io;
exports java.util;
// ...
}
<project>
<modelVersion>4.0.0</modelVersion>
<groupId>example</groupId>
<artifactId>bar</artifactId>
<version>1</version>
</project>
import sun.misc.Unsafe
module jdk.unsupported {
exports sun.misc;
// ...
}
module java.base {
exports java.lang;
exports java.io;
exports java.util;
// ...
}
import sun.misc.Unsafe
module jdk.unsupported {
exports sun.misc;
// ...
}
module example.bar {
requires jdk.unsupported;
}
Despite its name, the jdk.unsupported module is also contained in regular JVMs.
module sample.app {
requires foo.bar.qux;
requires some.lib;
}
java -p foo-bar-1.0.jar Main
java -p foo-bar-qux.jar Main
name version
module sample.app {
requires foo.bar.qux;
}
module some.lib {
requires foo.bar;
}
Automatic module names are instable because of:
1. The inpredictability of a jar's file name
2. The inpredictability of a dependencys future module name
Module names should follow the reverse DNS convention known from package names.
Ideally, a module name should be equal to the module's root package.
Avoid an impedance mismatch between module names and (Maven) artifact ids.
Automatic module names and module naming convention.
throws ResolutionException
Module-Name: foo.bar.qux
class foo.Bar class pkg.Main
Loading a class from the class path.
java 
–cp first.jar:second.jar:third.jar 
pkg.Main
Class<?> load(String className) {
for (JarFile jarFile : getClassPath()) {
if (jarFile.contains(className)) {
return jarFile.load(className);
}
}
throw new ClassNotFoundException(className);
}
class foo.Bar
Packages can be split among jars unless they are sealed. Yet, sealing is vulnerable.
search
order
Loading a class from the module path.
Map<String, Module> packageToModule;
Class<?> load(String className) {
Module module = packageToModule.get(pkgName(className));
if (module != null && module.contains(className)) {
return module.load(className);
}
throw new ClassNotFoundException(className);
}
example.foo example.bar
Module-Package-ownership: split packages or concealed packages are no longer permitted.
java 
–p first.jar:second.jar:third.jar 
–m example.foo/pkg.Main
module java.base
module java.scripting
module java.logging module java.instrument
module java.xml
module java.sql
module java.compiler
module java.datatransfer
module java.sql.rowset
module java.naming
module java.management
module java.rmi
module java.management.rmi
module java.prefs
module java.activation
module java.desktop
module java.corba
module java.transaction
module java.security.jgss
module java.security.sasl
module java.xml.crypto
module java.xml.bindmodule java.xml.ws
module java.xml.ws.annotation
package library;
class Api {
@Deprecated
String foo() {
return "foo";
}
String bar() {
return "bar";
}
}
package library;
class Api {
String foo() {
return "foo";
}
}
Dealing with "jar hell"
package library;
class Api {
String bar() {
return "bar";
}
}
library-1.0.jar library-2.0.jar
Api api = new Api();
api.foo();
second-library-1.0.jar
Api api = new Api();
api.bar();
third-library-1.0.jar
throws NoSuchMethodError
package library;
class Api {
String foo() {
return "foo";
}
}
package library;
class Api2 {
String bar() {
return "bar";
}
}
library-1.0.jar library-2.0.jar
Class<?> entryPoint = ModuleLayer.empty()
.defineModules(
Configuration.resolve(ModuleFinder.of(modsDir),
Collections.emptyList(),
ModuleFinder.of(), // no late resolved modules
Collections.singleton("my.module")),
name -> makeClassLoader(name)
).layer().findLoader("my.module").loadClass("my.Main");
With little tweaking, the JPMS is however already capable of isolating packages:
Jars, modular jars and jmods.
javac 
-d target 
src/module-info.java src/pkg/Main.java
jar 
--create
--file lib/example.foo.jar
--main-class=com.greetings.Main
-C target
.
jmod 
create
--class-path target
--main-class=com.greetings.Main
lib/example.foo.jmod
JMOD
A jar file containing a module-info.class is considered a modular jar.
Both the jar and the jmod tool support a --module-version parameter.
Versions are however not currently a part of JPMS, “jar hell” is therefore not averted.
Linking modules prior to execution.
jlink 
–-module-path ${JAVA_HOME}/jmods:mods 
--add-modules example.foo 
--launcher run=example.foo/pkg.Main
--output myapp
/myapp
/bin
java
run
/conf
/include
/legal
/lib
release./myapp/bin/run
Hello world!
du –hs myapp
44M myapp
./myapp/bin/java --list-modules
example.foo
java.base@9
Jlink (as of today) can only process jmods and modular jars.
package api;
public class SomeClass {
public void foo() {
/* do something */
}
private void bar() {
/* do something */
}
}
Method foo = SomeClass.class.getMethod("foo");
foo.invoke(new SomeClass());
Method bar = SomeClass.class.getDeclaredMethod("bar");
bar.setAccessible(true); // check against security manager
bar.invoke(new SomeClass());
Reflection and breaking encapsulation
module example.foo {
opens api;
}
open module example.foo { }
JVM modules do not open any of their packages (unless specified on the command line)!
java --add-opens
java --illegal-access=<permit,deny>
Module::addOpens
Instrumentation::redefineModule
module my.app {
requires spring;
requires hibernate;
}
module spring {
// ...
}
module hibernate {
// ...
}
open module my.app {
requires spring;
requires hibernate;
}
module my.app {
requires spring;
requires hibernate;
opens beans;
opens dtos;
} package beans;
interface MyBean {
void foo();
}
package internal;
class MyBeanImpl
implements MyBean {
@Override
public void foo() {
/* ... */
}
}
Object foo = ...
foo.getClass()
.getMethod("qux")
.invoke(foo);
module java.base {
exports java.lang;
// ...
}
module my.library { }
Field value = String.class.getDeclaredField("value");
value.setAccessible(true); // java.lang is not 'open'
Reflection against closed APIs is not discovered by the jdeps tool.
An existing class-path application that compiles and
runs on Java SE 8 will, thus, compile and run in
exactly the same way on Java SE 9, so long as it only
uses standard, non-deprecated Java SE APIs.
An existing class-path application that compiles and
runs on Java SE 8 will, thus, compile and run in
exactly the same way on Java SE 9, so long as it only
uses standard, non-deprecated Java SE APIs,
excluding the use of reflection on non-public members.
JPMS
group
package java.lang;
public class ClassLoader {
protected Class<?> defineClass(String name, byte[] b,
int off, int len) {
/* define class and return */
}
}
public class MyBean
{
public void foo() { }
void bar() { }
}
public class ProxyBean extends MyBean
{
@Override public void foo() { }
@Override void bar() { }
}
MyBean mock = Mockito.mock(MyBean.class);
MyBean persisted = entityManager.merge(myBean);
MyBean bean = applicationContext.getBean(MyBean.class);
ClassLoader proxyLoader = new ProxyClassLoader(parent);
Class<?> proxy = proxyLoader.loadClass("ProxyBean");
MethodHandles.Lookup lookup = MethodHandles.lookup();
lookup.defineClass(classFile);
MethodHandle bar = lookup.findVirtual(MyBean.class,
"bar",
MethodType.methodType(void.class);
bar.invoke(new MyBean());
MyBean mock = Mockito.mock(
MyBean.class, MethodHandles.lookup());
module my.library {
requires jdk.unsupported;
}
module jdk.unsupported {
exports sun.misc;
opens sun.misc;
// ...
}
module java.base {
exports java.lang;
// ...
}
Field theUnsafe = Unsafe.class.getDeclaredField("theUnsafe");
theUnsafe.setAccessible(true);
Unsafe unsafe = (Unsafe) theUnsafe.get(null);
unsafe.defineClass( ... );
package java.lang;
public class Accessor {
public void access() {
// within module
}
}
module my.library { }
Field value = String.class.getDeclaredField("value");
value.setAccessible(true); // java.lang is not 'open'
module example.service {
requires example.spi;
provides pkg.MyService
with impl.MyServiceImpl;
}
module example.spi {
exports pkg.MyService;
}
module example.app {
requires example.spi;
uses pkg.MyService;
}
interface MyService {
String hello();
}
class MyServiceImpl
implements MyService {
String hello() {
return "foo";
}
}
MyService service =
ServiceLoader.load(
MyService.class);
LOL
Compatible with non-modularized META-INF/services entries.
public class SomeHttpClient {
void call(String url) {
try {
Class.forName("org.apache.http.client.HttpClient");
ApacheDispatcher.doCall(HttpClients.createDefault());
} catch (ClassNotFoundException ignored) {
JVMDispatcher.doCall(new URL(url).openConnection());
}
}
}
module library.http {
requires static
httpclient;
}
<dependencies>
<dependency>
<groupId>org.apache.httpcomponents</groupId>
<artifactId>httpclient</artifactId>
<version>2.0</version>
<optional>true</optional>
</dependency>
</dependencies>
Could be substituted by using a service loader and modules that implement the binding.
module my.app {
requires spring;
opens beans;
}
module my.app {
requires spring;
requires careless.lib;
opens beans to spring;
}
module my.app {
requires spring;
requires careless.lib;
opens beans;
}
module spring {
// ...
}
module careless.lib {
// has vulnerability
}
class Util {
void doCall(String httpVal)
throws Exception {
Class.forName(httpVal)
.getMethod("apply")
.invoke(null);
}
}
It is also possible to qualify exports statements for the creation of friend modules.
This can be useful for priviledged modules within the same module family.
module my.app {
requires web.framework;
opens app;
}
URL ressource = getClass().getResource("/foo/bar.txt");
Resources are only visible to other modules if:
1. They reside in an exported package
2. Belong to the module conducting the lookup
3. Reside in a folder that is not a legal package-name (e.g. META-INF)
4. End with .class
/app/MyWebPage.java
/app/MyWebPage.html
abstract class BaseWebPage {
URL findTemplate() {
String name = getClass()
.getSimpleName() + ".html";
return getClass()
.getResource(name);
}
}
module web.framework {
// ...
}
module my.app {
requires web.framework;
}
class MyWebPage
extends BaseWebPage {
/* ... */
}
Alternative Java module systems: OSGi and JBoss modules
abstract class ClassLoader {
final ClassLoader parent;
Class<?> findClass(String name) {
/* 1. Call parent.findClass
2. Call this.loadClass */
}
Class<?> loadClass(String name) { /* ... */ }
}
class MyModuleClassLoader extends ClassLoader {
final Set<String> selfOwned;
final Map<String, ClassLoader> visible;
@Override Class<?> findClass(String name) {
String pkg = packageOf(name);
if (selfOwned.contains(pkg)) {
return loadClass(name);
}
ClassLoader delegate = visible.get(pkg);
if (delegate != null) {
return delegate.findClass(name);
} else {
throw new ClassNotFoundException();
}
}
@Override Class<?> loadClass(String name) { /* ... */ }
}
Bundle-Name: sampleapp
Bundle-SymbolicName: my.app
Bundle-Version: 1.0
Bundle-Activator: my.Main
Import-Package: some.lib;version="1.0"
Export-Package: my.pkg;version="1.0"
@BundleName("sampleapp")
@BundleActivator(Main.class)
module my.app {
requires osgi.api;
requires some.lib;
exports my.pkg;
}
class Foo {
String bar() { return "bar"; }
}
assertThat(new Foo().bar(), is("Hello World!"));
public static void premain(String arguments,
Instrumentation instrumentation) {
new AgentBuilder.Default()
.type(named("Foo"))
.transform((builder, type, loader, module) ->
builder.method(named("bar"))
.intercept(value("Hello World!"));
)
.installOn(instrumentation);
}
Java agents with Byte Buddy
class Foo {
String bar() {
long start = System.currentTimeMillis();
try {
return somethingComplex();
} finally {
AgentApi.report("Foo", "bar",
System.currentTimeMillis() - start);
}
}
}
class Foo {
String bar(InternalState state) {
long start = System.currentTimeMillis();
try {
return somethingComplex();
} finally {
AgentApi.report("Foo", "bar", state,
System.currentTimeMillis() - start);
}
}
}
class Foo {
String bar() {
return somethingComplex();
}
}
module some.app { }
Java agents are capable of breaking module boundaries:
interface Instrumentation {
void redefineModule(Module module,
Set<Module> extraReads,
Map<String, Set<Module>> extraExports,
Map<String, Set<Module>> extraOpens,
Set<Class<?>> extraUses,
Map<Class<?>, List<Class<?>>> extraProvides);
}
module some.app { exports internal.state; }
static void agentmain(String arg,
Instrumentation inst) {
/* ... */
}
processIdstart()
static void agentmain(String arg,
Instrumentation inst) {
/* ... */
}
String processId = ...
com.sun.tools.attach.VirtualMachine
.attach(processId)
.loadAgent(jarFile, argument);
class Foo {
void bar() {
/* ... */
}
}
class Foo$Mock extends Foo {
@Override void bar() {
Mockito.doMock();
}
}
class Foo {
void bar() {
if (Mockito.isMock(this)) {
Mockito.doMock();
return;
}
/* ... */
}
}
String processId = ...
com.sun.tools.attach.VirtualMachine
.attach(processId)
.loadAgent(jarFile, argument);
processId
processId
new ProcessBuilder(
"java attach.Helper <processId>"
).start();
-Djdk.attach.allowAttachSelf=false
Java platform module system: the controversy
Are modules even (still/even) useful?
Considering microservices, modules are often the better option, both considering
maintainability and performance. We have always used modules with Maven; adding
first-level support offers a chance to better interact with them at runtime.
Think of what we could have instead of Jigsaw in the time it took!
Remember the last time you had to defend a refactoring/maintenance release?
You should always clean up before you expand your feature set.
Java modules breaks all the things!
The "growth only" model is not sustainable if Java should have a future. The JVM
must at some point apply breaking changes to survive/strive.
To make full use of Java, some code needs to cross module boundaries!
Nobody relies on internal APIs for laziness but because it is necessary. Without the
openness of sun.misc.Unsafe in the past, a lot of libraries that make the JVM such
an attractive choice would not exist today. The standard library only offers basic
functionality by design. Especially test libraries and tooling have a legitimate wish
to "cross the line". As of today, any code can however still use Unsafe to leverage
low-level functionality. The standard library still relies heavily on qualified exports!
http://rafael.codes
@rafaelcodes
http://documents4j.com
https://github.com/documents4j/documents4j
http://bytebuddy.net
https://github.com/raphw/byte-buddy

Weitere Àhnliche Inhalte

Was ist angesagt?

Monitoring distributed (micro-)services
Monitoring distributed (micro-)servicesMonitoring distributed (micro-)services
Monitoring distributed (micro-)servicesRafael Winterhalter
 
æŻ”XMLæ›Žć„œç”šçš„Java Annotation
æŻ”XMLæ›Žć„œç”šçš„Java AnnotationæŻ”XMLæ›Žć„œç”šçš„Java Annotation
æŻ”XMLæ›Žć„œç”šçš„Java Annotationjavatwo2011
 
Java 5 and 6 New Features
Java 5 and 6 New FeaturesJava 5 and 6 New Features
Java 5 and 6 New FeaturesJussi Pohjolainen
 
Java Bytecode For Discriminating Developers - GeeCON 2011
Java Bytecode For Discriminating Developers - GeeCON 2011Java Bytecode For Discriminating Developers - GeeCON 2011
Java Bytecode For Discriminating Developers - GeeCON 2011Anton Arhipov
 
Mastering Java Bytecode - JAX.de 2012
Mastering Java Bytecode - JAX.de 2012Mastering Java Bytecode - JAX.de 2012
Mastering Java Bytecode - JAX.de 2012Anton Arhipov
 
Java Bytecode for Discriminating Developers - JavaZone 2011
Java Bytecode for Discriminating Developers - JavaZone 2011Java Bytecode for Discriminating Developers - JavaZone 2011
Java Bytecode for Discriminating Developers - JavaZone 2011Anton Arhipov
 
ëȘšë˜ìžë°”의 역슔
ëȘšë˜ìžë°”의 역슔ëȘšë˜ìžë°”의 역슔
ëȘšë˜ìžë°”의 역슔DoHyun Jung
 
Advance Java Programs skeleton
Advance Java Programs skeletonAdvance Java Programs skeleton
Advance Java Programs skeletonIram Ramrajkar
 
Java7 New Features and Code Examples
Java7 New Features and Code ExamplesJava7 New Features and Code Examples
Java7 New Features and Code ExamplesNaresh Chintalcheru
 
Jdk 7 4-forkjoin
Jdk 7 4-forkjoinJdk 7 4-forkjoin
Jdk 7 4-forkjoinknight1128
 
Jdk(java) 7 - 6 Ʞ타Ʞ늄
Jdk(java) 7 - 6 Ʞ타Ʞ늄Jdk(java) 7 - 6 Ʞ타Ʞ늄
Jdk(java) 7 - 6 Ʞ타Ʞ늄knight1128
 
What's new in Java EE 6
What's new in Java EE 6What's new in Java EE 6
What's new in Java EE 6Antonio Goncalves
 
To inject or not to inject: CDI is the question
To inject or not to inject: CDI is the questionTo inject or not to inject: CDI is the question
To inject or not to inject: CDI is the questionAntonio Goncalves
 
Java concurrency questions and answers
Java concurrency questions and answers Java concurrency questions and answers
Java concurrency questions and answers CodeOps Technologies LLP
 
Whats New in Java 5, 6, & 7 (Webinar Presentation - June 2013)
Whats New in Java 5, 6, & 7 (Webinar Presentation - June 2013)Whats New in Java 5, 6, & 7 (Webinar Presentation - June 2013)
Whats New in Java 5, 6, & 7 (Webinar Presentation - June 2013)DevelopIntelligence
 

Was ist angesagt? (20)

Monitoring distributed (micro-)services
Monitoring distributed (micro-)servicesMonitoring distributed (micro-)services
Monitoring distributed (micro-)services
 
55 New Features in Java 7
55 New Features in Java 755 New Features in Java 7
55 New Features in Java 7
 
æŻ”XMLæ›Žć„œç”šçš„Java Annotation
æŻ”XMLæ›Žć„œç”šçš„Java AnnotationæŻ”XMLæ›Žć„œç”šçš„Java Annotation
æŻ”XMLæ›Žć„œç”šçš„Java Annotation
 
Java 5 and 6 New Features
Java 5 and 6 New FeaturesJava 5 and 6 New Features
Java 5 and 6 New Features
 
Java Bytecode For Discriminating Developers - GeeCON 2011
Java Bytecode For Discriminating Developers - GeeCON 2011Java Bytecode For Discriminating Developers - GeeCON 2011
Java Bytecode For Discriminating Developers - GeeCON 2011
 
Mastering Java Bytecode - JAX.de 2012
Mastering Java Bytecode - JAX.de 2012Mastering Java Bytecode - JAX.de 2012
Mastering Java Bytecode - JAX.de 2012
 
Byte code field report
Byte code field reportByte code field report
Byte code field report
 
Java Bytecode for Discriminating Developers - JavaZone 2011
Java Bytecode for Discriminating Developers - JavaZone 2011Java Bytecode for Discriminating Developers - JavaZone 2011
Java Bytecode for Discriminating Developers - JavaZone 2011
 
ëȘšë˜ìžë°”의 역슔
ëȘšë˜ìžë°”의 역슔ëȘšë˜ìžë°”의 역슔
ëȘšë˜ìžë°”의 역슔
 
Advance Java Programs skeleton
Advance Java Programs skeletonAdvance Java Programs skeleton
Advance Java Programs skeleton
 
Java 7 New Features
Java 7 New FeaturesJava 7 New Features
Java 7 New Features
 
Java7 New Features and Code Examples
Java7 New Features and Code ExamplesJava7 New Features and Code Examples
Java7 New Features and Code Examples
 
Jdk 7 4-forkjoin
Jdk 7 4-forkjoinJdk 7 4-forkjoin
Jdk 7 4-forkjoin
 
JDK Power Tools
JDK Power ToolsJDK Power Tools
JDK Power Tools
 
Jdk(java) 7 - 6 Ʞ타Ʞ늄
Jdk(java) 7 - 6 Ʞ타Ʞ늄Jdk(java) 7 - 6 Ʞ타Ʞ늄
Jdk(java) 7 - 6 Ʞ타Ʞ늄
 
What's new in Java EE 6
What's new in Java EE 6What's new in Java EE 6
What's new in Java EE 6
 
To inject or not to inject: CDI is the question
To inject or not to inject: CDI is the questionTo inject or not to inject: CDI is the question
To inject or not to inject: CDI is the question
 
JDK1.6
JDK1.6JDK1.6
JDK1.6
 
Java concurrency questions and answers
Java concurrency questions and answers Java concurrency questions and answers
Java concurrency questions and answers
 
Whats New in Java 5, 6, & 7 (Webinar Presentation - June 2013)
Whats New in Java 5, 6, & 7 (Webinar Presentation - June 2013)Whats New in Java 5, 6, & 7 (Webinar Presentation - June 2013)
Whats New in Java 5, 6, & 7 (Webinar Presentation - June 2013)
 

Ähnlich wie Getting started with Java 9 modules

An Overview of Project Jigsaw
An Overview of Project JigsawAn Overview of Project Jigsaw
An Overview of Project JigsawRafael Winterhalter
 
Pom configuration java xml
Pom configuration java xmlPom configuration java xml
Pom configuration java xmlakmini
 
Pom
PomPom
Pomakmini
 
Introduction to OSGi
Introduction to OSGiIntroduction to OSGi
Introduction to OSGipradeepfn
 
ElsassJUG - Le classpath n'est pas mort...
ElsassJUG - Le classpath n'est pas mort...ElsassJUG - Le classpath n'est pas mort...
ElsassJUG - Le classpath n'est pas mort...Alexis Hassler
 
Internal Android Library Management (DroidCon SF 2016, Droidcon Italy 2016)
Internal Android Library Management (DroidCon SF 2016, Droidcon Italy 2016)Internal Android Library Management (DroidCon SF 2016, Droidcon Italy 2016)
Internal Android Library Management (DroidCon SF 2016, Droidcon Italy 2016)Kelly Shuster
 
Spring Boot and JHipster
Spring Boot and JHipsterSpring Boot and JHipster
Spring Boot and JHipsterEueung Mulyana
 
Moving to Module: Issues & Solutions
Moving to Module: Issues & SolutionsMoving to Module: Issues & Solutions
Moving to Module: Issues & SolutionsYuichi Sakuraba
 
Dependency injection in scala
Dependency injection in scalaDependency injection in scala
Dependency injection in scalaMichal Bigos
 
Reusable Ruby ‱ Rt 9 Ruby Group ‱ Jun 2012
Reusable Ruby ‱ Rt 9 Ruby Group ‱ Jun 2012Reusable Ruby ‱ Rt 9 Ruby Group ‱ Jun 2012
Reusable Ruby ‱ Rt 9 Ruby Group ‱ Jun 2012skinandbones
 
Aplicacoes dinamicas Rails com Backbone
Aplicacoes dinamicas Rails com BackboneAplicacoes dinamicas Rails com Backbone
Aplicacoes dinamicas Rails com BackboneRafael Felix da Silva
 
How to create a skeleton of a Java console application
How to create a skeleton of a Java console applicationHow to create a skeleton of a Java console application
How to create a skeleton of a Java console applicationDmitri Pisarenko
 
Android Internal Library Management
Android Internal Library ManagementAndroid Internal Library Management
Android Internal Library ManagementKelly Shuster
 
Arquillian in a nutshell
Arquillian in a nutshellArquillian in a nutshell
Arquillian in a nutshellBrockhaus Group
 
JSF, Facelets, Spring-JSF & Maven
JSF, Facelets, Spring-JSF & MavenJSF, Facelets, Spring-JSF & Maven
JSF, Facelets, Spring-JSF & MavenRaghavan Mohan
 
Hands On with Maven
Hands On with MavenHands On with Maven
Hands On with MavenSid Anand
 
FASTEN presentation at SFScon, November 2020
FASTEN presentation at SFScon, November 2020FASTEN presentation at SFScon, November 2020
FASTEN presentation at SFScon, November 2020Fasten Project
 
Java 9: Deep Dive into Modularity and Dealing with Migration Issues
Java 9: Deep Dive into Modularity and Dealing with Migration IssuesJava 9: Deep Dive into Modularity and Dealing with Migration Issues
Java 9: Deep Dive into Modularity and Dealing with Migration IssuesGlobalLogic Ukraine
 

Ähnlich wie Getting started with Java 9 modules (20)

An Overview of Project Jigsaw
An Overview of Project JigsawAn Overview of Project Jigsaw
An Overview of Project Jigsaw
 
Pom configuration java xml
Pom configuration java xmlPom configuration java xml
Pom configuration java xml
 
Pom
PomPom
Pom
 
Introduction to OSGi
Introduction to OSGiIntroduction to OSGi
Introduction to OSGi
 
ElsassJUG - Le classpath n'est pas mort...
ElsassJUG - Le classpath n'est pas mort...ElsassJUG - Le classpath n'est pas mort...
ElsassJUG - Le classpath n'est pas mort...
 
Internal Android Library Management (DroidCon SF 2016, Droidcon Italy 2016)
Internal Android Library Management (DroidCon SF 2016, Droidcon Italy 2016)Internal Android Library Management (DroidCon SF 2016, Droidcon Italy 2016)
Internal Android Library Management (DroidCon SF 2016, Droidcon Italy 2016)
 
Spring Boot and JHipster
Spring Boot and JHipsterSpring Boot and JHipster
Spring Boot and JHipster
 
Moving to Module: Issues & Solutions
Moving to Module: Issues & SolutionsMoving to Module: Issues & Solutions
Moving to Module: Issues & Solutions
 
Dependency injection in scala
Dependency injection in scalaDependency injection in scala
Dependency injection in scala
 
Migrating to Java 9 Modules
Migrating to Java 9 ModulesMigrating to Java 9 Modules
Migrating to Java 9 Modules
 
Reusable Ruby ‱ Rt 9 Ruby Group ‱ Jun 2012
Reusable Ruby ‱ Rt 9 Ruby Group ‱ Jun 2012Reusable Ruby ‱ Rt 9 Ruby Group ‱ Jun 2012
Reusable Ruby ‱ Rt 9 Ruby Group ‱ Jun 2012
 
Aplicacoes dinamicas Rails com Backbone
Aplicacoes dinamicas Rails com BackboneAplicacoes dinamicas Rails com Backbone
Aplicacoes dinamicas Rails com Backbone
 
How to create a skeleton of a Java console application
How to create a skeleton of a Java console applicationHow to create a skeleton of a Java console application
How to create a skeleton of a Java console application
 
Android Internal Library Management
Android Internal Library ManagementAndroid Internal Library Management
Android Internal Library Management
 
Arquillian in a nutshell
Arquillian in a nutshellArquillian in a nutshell
Arquillian in a nutshell
 
JSF, Facelets, Spring-JSF & Maven
JSF, Facelets, Spring-JSF & MavenJSF, Facelets, Spring-JSF & Maven
JSF, Facelets, Spring-JSF & Maven
 
Arquillian in a nutshell
Arquillian in a nutshellArquillian in a nutshell
Arquillian in a nutshell
 
Hands On with Maven
Hands On with MavenHands On with Maven
Hands On with Maven
 
FASTEN presentation at SFScon, November 2020
FASTEN presentation at SFScon, November 2020FASTEN presentation at SFScon, November 2020
FASTEN presentation at SFScon, November 2020
 
Java 9: Deep Dive into Modularity and Dealing with Migration Issues
Java 9: Deep Dive into Modularity and Dealing with Migration IssuesJava 9: Deep Dive into Modularity and Dealing with Migration Issues
Java 9: Deep Dive into Modularity and Dealing with Migration Issues
 

Mehr von Rafael Winterhalter

The definitive guide to java agents
The definitive guide to java agentsThe definitive guide to java agents
The definitive guide to java agentsRafael Winterhalter
 
Event-Sourcing Microservices on the JVM
Event-Sourcing Microservices on the JVMEvent-Sourcing Microservices on the JVM
Event-Sourcing Microservices on the JVMRafael Winterhalter
 
The Java memory model made easy
The Java memory model made easyThe Java memory model made easy
The Java memory model made easyRafael Winterhalter
 
An introduction to JVM performance
An introduction to JVM performanceAn introduction to JVM performance
An introduction to JVM performanceRafael Winterhalter
 
Java byte code in practice
Java byte code in practiceJava byte code in practice
Java byte code in practiceRafael Winterhalter
 
Unit testing concurrent code
Unit testing concurrent codeUnit testing concurrent code
Unit testing concurrent codeRafael Winterhalter
 
Understanding Java byte code and the class file format
Understanding Java byte code and the class file formatUnderstanding Java byte code and the class file format
Understanding Java byte code and the class file formatRafael Winterhalter
 
A topology of memory leaks on the JVM
A topology of memory leaks on the JVMA topology of memory leaks on the JVM
A topology of memory leaks on the JVMRafael Winterhalter
 

Mehr von Rafael Winterhalter (9)

The definitive guide to java agents
The definitive guide to java agentsThe definitive guide to java agents
The definitive guide to java agents
 
Event-Sourcing Microservices on the JVM
Event-Sourcing Microservices on the JVMEvent-Sourcing Microservices on the JVM
Event-Sourcing Microservices on the JVM
 
Migrating to JUnit 5
Migrating to JUnit 5Migrating to JUnit 5
Migrating to JUnit 5
 
The Java memory model made easy
The Java memory model made easyThe Java memory model made easy
The Java memory model made easy
 
An introduction to JVM performance
An introduction to JVM performanceAn introduction to JVM performance
An introduction to JVM performance
 
Java byte code in practice
Java byte code in practiceJava byte code in practice
Java byte code in practice
 
Unit testing concurrent code
Unit testing concurrent codeUnit testing concurrent code
Unit testing concurrent code
 
Understanding Java byte code and the class file format
Understanding Java byte code and the class file formatUnderstanding Java byte code and the class file format
Understanding Java byte code and the class file format
 
A topology of memory leaks on the JVM
A topology of memory leaks on the JVMA topology of memory leaks on the JVM
A topology of memory leaks on the JVM
 

KĂŒrzlich hochgeladen

call girls in Vaishali (Ghaziabad) 🔝 >àŒ’8448380779 🔝 genuine Escort Service đŸ”âœ”ïžâœ”ïž
call girls in Vaishali (Ghaziabad) 🔝 >àŒ’8448380779 🔝 genuine Escort Service đŸ”âœ”ïžâœ”ïžcall girls in Vaishali (Ghaziabad) 🔝 >àŒ’8448380779 🔝 genuine Escort Service đŸ”âœ”ïžâœ”ïž
call girls in Vaishali (Ghaziabad) 🔝 >àŒ’8448380779 🔝 genuine Escort Service đŸ”âœ”ïžâœ”ïžDelhi Call girls
 
Right Money Management App For Your Financial Goals
Right Money Management App For Your Financial GoalsRight Money Management App For Your Financial Goals
Right Money Management App For Your Financial GoalsJhone kinadey
 
A Secure and Reliable Document Management System is Essential.docx
A Secure and Reliable Document Management System is Essential.docxA Secure and Reliable Document Management System is Essential.docx
A Secure and Reliable Document Management System is Essential.docxComplianceQuest1
 
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...panagenda
 
(Genuine) Escort Service Lucknow | Starting â‚č,5K To @25k with A/C đŸ§‘đŸœâ€â€ïžâ€đŸ§‘đŸ» 89...
(Genuine) Escort Service Lucknow | Starting â‚č,5K To @25k with A/C đŸ§‘đŸœâ€â€ïžâ€đŸ§‘đŸ» 89...(Genuine) Escort Service Lucknow | Starting â‚č,5K To @25k with A/C đŸ§‘đŸœâ€â€ïžâ€đŸ§‘đŸ» 89...
(Genuine) Escort Service Lucknow | Starting â‚č,5K To @25k with A/C đŸ§‘đŸœâ€â€ïžâ€đŸ§‘đŸ» 89...gurkirankumar98700
 
Unlocking the Future of AI Agents with Large Language Models
Unlocking the Future of AI Agents with Large Language ModelsUnlocking the Future of AI Agents with Large Language Models
Unlocking the Future of AI Agents with Large Language Modelsaagamshah0812
 
why an Opensea Clone Script might be your perfect match.pdf
why an Opensea Clone Script might be your perfect match.pdfwhy an Opensea Clone Script might be your perfect match.pdf
why an Opensea Clone Script might be your perfect match.pdfjoe51371421
 
TECUNIQUE: Success Stories: IT Service provider
TECUNIQUE: Success Stories: IT Service providerTECUNIQUE: Success Stories: IT Service provider
TECUNIQUE: Success Stories: IT Service providermohitmore19
 
How To Troubleshoot Collaboration Apps for the Modern Connected Worker
How To Troubleshoot Collaboration Apps for the Modern Connected WorkerHow To Troubleshoot Collaboration Apps for the Modern Connected Worker
How To Troubleshoot Collaboration Apps for the Modern Connected WorkerThousandEyes
 
5 Signs You Need a Fashion PLM Software.pdf
5 Signs You Need a Fashion PLM Software.pdf5 Signs You Need a Fashion PLM Software.pdf
5 Signs You Need a Fashion PLM Software.pdfWave PLM
 
Hand gesture recognition PROJECT PPT.pptx
Hand gesture recognition PROJECT PPT.pptxHand gesture recognition PROJECT PPT.pptx
Hand gesture recognition PROJECT PPT.pptxbodapatigopi8531
 
Test Automation Strategy for Frontend and Backend
Test Automation Strategy for Frontend and BackendTest Automation Strategy for Frontend and Backend
Test Automation Strategy for Frontend and BackendArshad QA
 
Active Directory Penetration Testing, cionsystems.com.pdf
Active Directory Penetration Testing, cionsystems.com.pdfActive Directory Penetration Testing, cionsystems.com.pdf
Active Directory Penetration Testing, cionsystems.com.pdfCionsystems
 
CALL ON ➄8923113531 🔝Call Girls Kakori Lucknow best sexual service Online ☂
CALL ON ➄8923113531 🔝Call Girls Kakori Lucknow best sexual service Online  ☂CALL ON ➄8923113531 🔝Call Girls Kakori Lucknow best sexual service Online  ☂
CALL ON ➄8923113531 🔝Call Girls Kakori Lucknow best sexual service Online ☂anilsa9823
 
Unveiling the Tech Salsa of LAMs with Janus in Real-Time Applications
Unveiling the Tech Salsa of LAMs with Janus in Real-Time ApplicationsUnveiling the Tech Salsa of LAMs with Janus in Real-Time Applications
Unveiling the Tech Salsa of LAMs with Janus in Real-Time ApplicationsAlberto GonzĂĄlez Trastoy
 
DNT_Corporate presentation know about us
DNT_Corporate presentation know about usDNT_Corporate presentation know about us
DNT_Corporate presentation know about usDynamic Netsoft
 
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...ICS
 
Advancing Engineering with AI through the Next Generation of Strategic Projec...
Advancing Engineering with AI through the Next Generation of Strategic Projec...Advancing Engineering with AI through the Next Generation of Strategic Projec...
Advancing Engineering with AI through the Next Generation of Strategic Projec...OnePlan Solutions
 
SyndBuddy AI 2k Review 2024: Revolutionizing Content Syndication with AI
SyndBuddy AI 2k Review 2024: Revolutionizing Content Syndication with AISyndBuddy AI 2k Review 2024: Revolutionizing Content Syndication with AI
SyndBuddy AI 2k Review 2024: Revolutionizing Content Syndication with AIABDERRAOUF MEHENNI
 

KĂŒrzlich hochgeladen (20)

call girls in Vaishali (Ghaziabad) 🔝 >àŒ’8448380779 🔝 genuine Escort Service đŸ”âœ”ïžâœ”ïž
call girls in Vaishali (Ghaziabad) 🔝 >àŒ’8448380779 🔝 genuine Escort Service đŸ”âœ”ïžâœ”ïžcall girls in Vaishali (Ghaziabad) 🔝 >àŒ’8448380779 🔝 genuine Escort Service đŸ”âœ”ïžâœ”ïž
call girls in Vaishali (Ghaziabad) 🔝 >àŒ’8448380779 🔝 genuine Escort Service đŸ”âœ”ïžâœ”ïž
 
Right Money Management App For Your Financial Goals
Right Money Management App For Your Financial GoalsRight Money Management App For Your Financial Goals
Right Money Management App For Your Financial Goals
 
A Secure and Reliable Document Management System is Essential.docx
A Secure and Reliable Document Management System is Essential.docxA Secure and Reliable Document Management System is Essential.docx
A Secure and Reliable Document Management System is Essential.docx
 
Exploring iOS App Development: Simplifying the Process
Exploring iOS App Development: Simplifying the ProcessExploring iOS App Development: Simplifying the Process
Exploring iOS App Development: Simplifying the Process
 
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...
W01_panagenda_Navigating-the-Future-with-The-Hitchhikers-Guide-to-Notes-and-D...
 
(Genuine) Escort Service Lucknow | Starting â‚č,5K To @25k with A/C đŸ§‘đŸœâ€â€ïžâ€đŸ§‘đŸ» 89...
(Genuine) Escort Service Lucknow | Starting â‚č,5K To @25k with A/C đŸ§‘đŸœâ€â€ïžâ€đŸ§‘đŸ» 89...(Genuine) Escort Service Lucknow | Starting â‚č,5K To @25k with A/C đŸ§‘đŸœâ€â€ïžâ€đŸ§‘đŸ» 89...
(Genuine) Escort Service Lucknow | Starting â‚č,5K To @25k with A/C đŸ§‘đŸœâ€â€ïžâ€đŸ§‘đŸ» 89...
 
Unlocking the Future of AI Agents with Large Language Models
Unlocking the Future of AI Agents with Large Language ModelsUnlocking the Future of AI Agents with Large Language Models
Unlocking the Future of AI Agents with Large Language Models
 
why an Opensea Clone Script might be your perfect match.pdf
why an Opensea Clone Script might be your perfect match.pdfwhy an Opensea Clone Script might be your perfect match.pdf
why an Opensea Clone Script might be your perfect match.pdf
 
TECUNIQUE: Success Stories: IT Service provider
TECUNIQUE: Success Stories: IT Service providerTECUNIQUE: Success Stories: IT Service provider
TECUNIQUE: Success Stories: IT Service provider
 
How To Troubleshoot Collaboration Apps for the Modern Connected Worker
How To Troubleshoot Collaboration Apps for the Modern Connected WorkerHow To Troubleshoot Collaboration Apps for the Modern Connected Worker
How To Troubleshoot Collaboration Apps for the Modern Connected Worker
 
5 Signs You Need a Fashion PLM Software.pdf
5 Signs You Need a Fashion PLM Software.pdf5 Signs You Need a Fashion PLM Software.pdf
5 Signs You Need a Fashion PLM Software.pdf
 
Hand gesture recognition PROJECT PPT.pptx
Hand gesture recognition PROJECT PPT.pptxHand gesture recognition PROJECT PPT.pptx
Hand gesture recognition PROJECT PPT.pptx
 
Test Automation Strategy for Frontend and Backend
Test Automation Strategy for Frontend and BackendTest Automation Strategy for Frontend and Backend
Test Automation Strategy for Frontend and Backend
 
Active Directory Penetration Testing, cionsystems.com.pdf
Active Directory Penetration Testing, cionsystems.com.pdfActive Directory Penetration Testing, cionsystems.com.pdf
Active Directory Penetration Testing, cionsystems.com.pdf
 
CALL ON ➄8923113531 🔝Call Girls Kakori Lucknow best sexual service Online ☂
CALL ON ➄8923113531 🔝Call Girls Kakori Lucknow best sexual service Online  ☂CALL ON ➄8923113531 🔝Call Girls Kakori Lucknow best sexual service Online  ☂
CALL ON ➄8923113531 🔝Call Girls Kakori Lucknow best sexual service Online ☂
 
Unveiling the Tech Salsa of LAMs with Janus in Real-Time Applications
Unveiling the Tech Salsa of LAMs with Janus in Real-Time ApplicationsUnveiling the Tech Salsa of LAMs with Janus in Real-Time Applications
Unveiling the Tech Salsa of LAMs with Janus in Real-Time Applications
 
DNT_Corporate presentation know about us
DNT_Corporate presentation know about usDNT_Corporate presentation know about us
DNT_Corporate presentation know about us
 
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...
The Real-World Challenges of Medical Device Cybersecurity- Mitigating Vulnera...
 
Advancing Engineering with AI through the Next Generation of Strategic Projec...
Advancing Engineering with AI through the Next Generation of Strategic Projec...Advancing Engineering with AI through the Next Generation of Strategic Projec...
Advancing Engineering with AI through the Next Generation of Strategic Projec...
 
SyndBuddy AI 2k Review 2024: Revolutionizing Content Syndication with AI
SyndBuddy AI 2k Review 2024: Revolutionizing Content Syndication with AISyndBuddy AI 2k Review 2024: Revolutionizing Content Syndication with AI
SyndBuddy AI 2k Review 2024: Revolutionizing Content Syndication with AI
 

Getting started with Java 9 modules

  • 4. Scope Task module descriptor module descriptor deployment descriptor build execution descriptor API for custom tasks runtime compile-time build-time Type declarative declarative/programmatic Unit Java package (sub-)project
  • 5. api/Foo.class internal/Qux.class api/Bar.class internal/Baz.class api/Foo.class internal/Qux.class api/Bar.class internal/Baz.class (system) class path Modularity prior to Java 9 is emulated by class loader hierarchies. By tweaking class loaders to define multiple parents, it is also possible to run several versions of the same module (e.g. OSGi).
  • 6. api/Foo.class internal/Qux.class api/Bar.class internal/Baz.class api/Foo.class internal/Qux.class api/Bar.class internal/Baz.class module loader example.foo example.bar “example.bar reads example.foo” The integrity of the module graph is verified by the Java 9 runtime. Jars without a module-info.class are typically contained by the unnamed module that reads all modules.
  • 7. module example.qux { exports example.bar; } module example.foo { requires example.foo; exports api; } <project> <modelVersion>4.0.0</modelVersion> <groupId>example</groupId> <artifactId>qux</artifactId> <version>1</version> </project> <project> <modelVersion>4.0.0</modelVersion> <groupId>example</groupId> <artifactId>bar</artifactId> <version>1</version> </project> <project> <modelVersion>4.0.0</modelVersion> <groupId>example</groupId> <artifactId>foo</artifactId> <version>1</version> </project> module example.bar { requires example.foo; } module example.bar { requires transitive example.foo; } Imports are non-transitive by default (what is a good default for a runtime module system).
  • 8. module example.bar { requires example.foo; requires java.xml; } module java.base { exports java.lang; exports java.io; exports java.util; // ... } module java.xml { exports org.xml.sax; // ... } module example.foo { exports api; // ... }
  • 9. module example.bar { requires example.foo; requires java.xml; } <project> <modelVersion>4.0.0</modelVersion> <groupId>example</groupId> <artifactId>foo</artifactId> <version>1</version> </project> module java.base { exports java.lang; exports java.io; exports java.util; // ... } module java.xml { exports org.xml.sax; // ... } Modules can use non-modularized code as automatic modules (referenced by jar name). Automatic modules export every package and import any module. Automatic modules should only be used locally to avoid depending on a name. example-foo-1.jar
  • 10. module java.base { exports java.lang; exports java.io; exports java.util; // ... } module java.xml { exports org.xml.sax; // ... } module example.foo { exports api; // ... } <project> <modelVersion>4.0.0</modelVersion> <groupId>example</groupId> <artifactId>bar</artifactId> <version>1</version> </project> Non-modularized code can still run on the class path within the unnamed module. The unnamed module imports any module but does not export any packages.
  • 11. module java.base { exports java.lang; exports java.io; exports java.util; // ... } <project> <modelVersion>4.0.0</modelVersion> <groupId>example</groupId> <artifactId>bar</artifactId> <version>1</version> </project> import sun.misc.BASE64Encoder java --add-exports java.base/sun.misc=ALL-UNNAMED Module::addExport Module::addRead Instrumentation::redefineModule;
  • 12. module java.base { exports java.lang; exports java.io; exports java.util; // ... } <project> <modelVersion>4.0.0</modelVersion> <groupId>example</groupId> <artifactId>bar</artifactId> <version>1</version> </project> import sun.misc.Unsafe module jdk.unsupported { exports sun.misc; // ... }
  • 13. module java.base { exports java.lang; exports java.io; exports java.util; // ... } import sun.misc.Unsafe module jdk.unsupported { exports sun.misc; // ... } module example.bar { requires jdk.unsupported; } Despite its name, the jdk.unsupported module is also contained in regular JVMs.
  • 14. module sample.app { requires foo.bar.qux; requires some.lib; } java -p foo-bar-1.0.jar Main java -p foo-bar-qux.jar Main name version module sample.app { requires foo.bar.qux; } module some.lib { requires foo.bar; } Automatic module names are instable because of: 1. The inpredictability of a jar's file name 2. The inpredictability of a dependencys future module name Module names should follow the reverse DNS convention known from package names. Ideally, a module name should be equal to the module's root package. Avoid an impedance mismatch between module names and (Maven) artifact ids. Automatic module names and module naming convention. throws ResolutionException Module-Name: foo.bar.qux
  • 15. class foo.Bar class pkg.Main Loading a class from the class path. java –cp first.jar:second.jar:third.jar pkg.Main Class<?> load(String className) { for (JarFile jarFile : getClassPath()) { if (jarFile.contains(className)) { return jarFile.load(className); } } throw new ClassNotFoundException(className); } class foo.Bar Packages can be split among jars unless they are sealed. Yet, sealing is vulnerable. search order
  • 16. Loading a class from the module path. Map<String, Module> packageToModule; Class<?> load(String className) { Module module = packageToModule.get(pkgName(className)); if (module != null && module.contains(className)) { return module.load(className); } throw new ClassNotFoundException(className); } example.foo example.bar Module-Package-ownership: split packages or concealed packages are no longer permitted. java –p first.jar:second.jar:third.jar –m example.foo/pkg.Main
  • 17. module java.base module java.scripting module java.logging module java.instrument module java.xml module java.sql module java.compiler module java.datatransfer module java.sql.rowset module java.naming module java.management module java.rmi module java.management.rmi module java.prefs module java.activation module java.desktop module java.corba module java.transaction module java.security.jgss module java.security.sasl module java.xml.crypto module java.xml.bindmodule java.xml.ws module java.xml.ws.annotation
  • 18. package library; class Api { @Deprecated String foo() { return "foo"; } String bar() { return "bar"; } } package library; class Api { String foo() { return "foo"; } } Dealing with "jar hell" package library; class Api { String bar() { return "bar"; } } library-1.0.jar library-2.0.jar Api api = new Api(); api.foo(); second-library-1.0.jar Api api = new Api(); api.bar(); third-library-1.0.jar throws NoSuchMethodError
  • 19. package library; class Api { String foo() { return "foo"; } } package library; class Api2 { String bar() { return "bar"; } } library-1.0.jar library-2.0.jar Class<?> entryPoint = ModuleLayer.empty() .defineModules( Configuration.resolve(ModuleFinder.of(modsDir), Collections.emptyList(), ModuleFinder.of(), // no late resolved modules Collections.singleton("my.module")), name -> makeClassLoader(name) ).layer().findLoader("my.module").loadClass("my.Main"); With little tweaking, the JPMS is however already capable of isolating packages:
  • 20. Jars, modular jars and jmods. javac -d target src/module-info.java src/pkg/Main.java jar --create --file lib/example.foo.jar --main-class=com.greetings.Main -C target . jmod create --class-path target --main-class=com.greetings.Main lib/example.foo.jmod JMOD A jar file containing a module-info.class is considered a modular jar. Both the jar and the jmod tool support a --module-version parameter. Versions are however not currently a part of JPMS, “jar hell” is therefore not averted.
  • 21. Linking modules prior to execution. jlink –-module-path ${JAVA_HOME}/jmods:mods --add-modules example.foo --launcher run=example.foo/pkg.Main --output myapp /myapp /bin java run /conf /include /legal /lib release./myapp/bin/run Hello world! du –hs myapp 44M myapp ./myapp/bin/java --list-modules example.foo java.base@9 Jlink (as of today) can only process jmods and modular jars.
  • 22. package api; public class SomeClass { public void foo() { /* do something */ } private void bar() { /* do something */ } } Method foo = SomeClass.class.getMethod("foo"); foo.invoke(new SomeClass()); Method bar = SomeClass.class.getDeclaredMethod("bar"); bar.setAccessible(true); // check against security manager bar.invoke(new SomeClass()); Reflection and breaking encapsulation module example.foo { opens api; } open module example.foo { } JVM modules do not open any of their packages (unless specified on the command line)! java --add-opens java --illegal-access=<permit,deny> Module::addOpens Instrumentation::redefineModule
  • 23. module my.app { requires spring; requires hibernate; } module spring { // ... } module hibernate { // ... } open module my.app { requires spring; requires hibernate; } module my.app { requires spring; requires hibernate; opens beans; opens dtos; } package beans; interface MyBean { void foo(); } package internal; class MyBeanImpl implements MyBean { @Override public void foo() { /* ... */ } } Object foo = ... foo.getClass() .getMethod("qux") .invoke(foo);
  • 24. module java.base { exports java.lang; // ... } module my.library { } Field value = String.class.getDeclaredField("value"); value.setAccessible(true); // java.lang is not 'open' Reflection against closed APIs is not discovered by the jdeps tool. An existing class-path application that compiles and runs on Java SE 8 will, thus, compile and run in exactly the same way on Java SE 9, so long as it only uses standard, non-deprecated Java SE APIs. An existing class-path application that compiles and runs on Java SE 8 will, thus, compile and run in exactly the same way on Java SE 9, so long as it only uses standard, non-deprecated Java SE APIs, excluding the use of reflection on non-public members. JPMS group
  • 25. package java.lang; public class ClassLoader { protected Class<?> defineClass(String name, byte[] b, int off, int len) { /* define class and return */ } } public class MyBean { public void foo() { } void bar() { } } public class ProxyBean extends MyBean { @Override public void foo() { } @Override void bar() { } } MyBean mock = Mockito.mock(MyBean.class); MyBean persisted = entityManager.merge(myBean); MyBean bean = applicationContext.getBean(MyBean.class); ClassLoader proxyLoader = new ProxyClassLoader(parent); Class<?> proxy = proxyLoader.loadClass("ProxyBean"); MethodHandles.Lookup lookup = MethodHandles.lookup(); lookup.defineClass(classFile); MethodHandle bar = lookup.findVirtual(MyBean.class, "bar", MethodType.methodType(void.class); bar.invoke(new MyBean()); MyBean mock = Mockito.mock( MyBean.class, MethodHandles.lookup());
  • 26. module my.library { requires jdk.unsupported; } module jdk.unsupported { exports sun.misc; opens sun.misc; // ... } module java.base { exports java.lang; // ... } Field theUnsafe = Unsafe.class.getDeclaredField("theUnsafe"); theUnsafe.setAccessible(true); Unsafe unsafe = (Unsafe) theUnsafe.get(null); unsafe.defineClass( ... ); package java.lang; public class Accessor { public void access() { // within module } } module my.library { } Field value = String.class.getDeclaredField("value"); value.setAccessible(true); // java.lang is not 'open'
  • 27. module example.service { requires example.spi; provides pkg.MyService with impl.MyServiceImpl; } module example.spi { exports pkg.MyService; } module example.app { requires example.spi; uses pkg.MyService; } interface MyService { String hello(); } class MyServiceImpl implements MyService { String hello() { return "foo"; } } MyService service = ServiceLoader.load( MyService.class); LOL Compatible with non-modularized META-INF/services entries.
  • 28. public class SomeHttpClient { void call(String url) { try { Class.forName("org.apache.http.client.HttpClient"); ApacheDispatcher.doCall(HttpClients.createDefault()); } catch (ClassNotFoundException ignored) { JVMDispatcher.doCall(new URL(url).openConnection()); } } } module library.http { requires static httpclient; } <dependencies> <dependency> <groupId>org.apache.httpcomponents</groupId> <artifactId>httpclient</artifactId> <version>2.0</version> <optional>true</optional> </dependency> </dependencies> Could be substituted by using a service loader and modules that implement the binding.
  • 29. module my.app { requires spring; opens beans; } module my.app { requires spring; requires careless.lib; opens beans to spring; } module my.app { requires spring; requires careless.lib; opens beans; } module spring { // ... } module careless.lib { // has vulnerability } class Util { void doCall(String httpVal) throws Exception { Class.forName(httpVal) .getMethod("apply") .invoke(null); } } It is also possible to qualify exports statements for the creation of friend modules. This can be useful for priviledged modules within the same module family.
  • 30. module my.app { requires web.framework; opens app; } URL ressource = getClass().getResource("/foo/bar.txt"); Resources are only visible to other modules if: 1. They reside in an exported package 2. Belong to the module conducting the lookup 3. Reside in a folder that is not a legal package-name (e.g. META-INF) 4. End with .class /app/MyWebPage.java /app/MyWebPage.html abstract class BaseWebPage { URL findTemplate() { String name = getClass() .getSimpleName() + ".html"; return getClass() .getResource(name); } } module web.framework { // ... } module my.app { requires web.framework; } class MyWebPage extends BaseWebPage { /* ... */ }
  • 31. Alternative Java module systems: OSGi and JBoss modules abstract class ClassLoader { final ClassLoader parent; Class<?> findClass(String name) { /* 1. Call parent.findClass 2. Call this.loadClass */ } Class<?> loadClass(String name) { /* ... */ } } class MyModuleClassLoader extends ClassLoader { final Set<String> selfOwned; final Map<String, ClassLoader> visible; @Override Class<?> findClass(String name) { String pkg = packageOf(name); if (selfOwned.contains(pkg)) { return loadClass(name); } ClassLoader delegate = visible.get(pkg); if (delegate != null) { return delegate.findClass(name); } else { throw new ClassNotFoundException(); } } @Override Class<?> loadClass(String name) { /* ... */ } } Bundle-Name: sampleapp Bundle-SymbolicName: my.app Bundle-Version: 1.0 Bundle-Activator: my.Main Import-Package: some.lib;version="1.0" Export-Package: my.pkg;version="1.0" @BundleName("sampleapp") @BundleActivator(Main.class) module my.app { requires osgi.api; requires some.lib; exports my.pkg; }
  • 32. class Foo { String bar() { return "bar"; } } assertThat(new Foo().bar(), is("Hello World!")); public static void premain(String arguments, Instrumentation instrumentation) { new AgentBuilder.Default() .type(named("Foo")) .transform((builder, type, loader, module) -> builder.method(named("bar")) .intercept(value("Hello World!")); ) .installOn(instrumentation); } Java agents with Byte Buddy
  • 33. class Foo { String bar() { long start = System.currentTimeMillis(); try { return somethingComplex(); } finally { AgentApi.report("Foo", "bar", System.currentTimeMillis() - start); } } } class Foo { String bar(InternalState state) { long start = System.currentTimeMillis(); try { return somethingComplex(); } finally { AgentApi.report("Foo", "bar", state, System.currentTimeMillis() - start); } } } class Foo { String bar() { return somethingComplex(); } } module some.app { } Java agents are capable of breaking module boundaries: interface Instrumentation { void redefineModule(Module module, Set<Module> extraReads, Map<String, Set<Module>> extraExports, Map<String, Set<Module>> extraOpens, Set<Class<?>> extraUses, Map<Class<?>, List<Class<?>>> extraProvides); } module some.app { exports internal.state; }
  • 34. static void agentmain(String arg, Instrumentation inst) { /* ... */ } processIdstart() static void agentmain(String arg, Instrumentation inst) { /* ... */ } String processId = ... com.sun.tools.attach.VirtualMachine .attach(processId) .loadAgent(jarFile, argument); class Foo { void bar() { /* ... */ } } class Foo$Mock extends Foo { @Override void bar() { Mockito.doMock(); } } class Foo { void bar() { if (Mockito.isMock(this)) { Mockito.doMock(); return; } /* ... */ } } String processId = ... com.sun.tools.attach.VirtualMachine .attach(processId) .loadAgent(jarFile, argument); processId processId new ProcessBuilder( "java attach.Helper <processId>" ).start(); -Djdk.attach.allowAttachSelf=false
  • 35. Java platform module system: the controversy Are modules even (still/even) useful? Considering microservices, modules are often the better option, both considering maintainability and performance. We have always used modules with Maven; adding first-level support offers a chance to better interact with them at runtime. Think of what we could have instead of Jigsaw in the time it took! Remember the last time you had to defend a refactoring/maintenance release? You should always clean up before you expand your feature set. Java modules breaks all the things! The "growth only" model is not sustainable if Java should have a future. The JVM must at some point apply breaking changes to survive/strive. To make full use of Java, some code needs to cross module boundaries! Nobody relies on internal APIs for laziness but because it is necessary. Without the openness of sun.misc.Unsafe in the past, a lot of libraries that make the JVM such an attractive choice would not exist today. The standard library only offers basic functionality by design. Especially test libraries and tooling have a legitimate wish to "cross the line". As of today, any code can however still use Unsafe to leverage low-level functionality. The standard library still relies heavily on qualified exports!