SlideShare a Scribd company logo
Java 9 модули
Евгений Козлов, 19.05.2017
История версий Java
Версия Дата выхода Главные изменения
Java 1.4 06.02.2002 assert, NIO
Java 1.5 30.09.2004 enum, generics, annotations
Java 1.6 11.12.2006 @Override in interfaces, Deque
Java 1.7 07.07.2011 invokedynamic, try-with-resources
Java 1.8 18.03.2014 lambdas, default methods, Nashorn
Java 9 27.07.2017 modules, iface private methods, jshell
Java 9 модули
JDK 9
JEP 102: Process API Updates
JEP 110: HTTP 2 Client
JEP 143: Improve Contended Locking
JEP 158: Unified JVM Logging
JEP 165: Compiler Control
JEP 193: Variable Handles
JEP 197: Segmented Code Cache
JEP 199: Smart Java Compilation, Phase Two
JEP 200: The Modular JDK
JEP 201: Modular Source Code
JEP 211: Elide Deprecation Warnings on Import
Statements
JEP 212: Resolve Lint and Doclint Warnings
JEP 213: Milling Project Coin
JEP 214: Remove GC Combinations Deprecated in JDK 8
JEP 215: Tiered Attribution for javac
JEP 216: Process Import Statements Correctly
JEP 217: Annotations Pipeline 2.0
JEP 219: Datagram Transport Layer Security (DTLS)
JEP 220: Modular Run-Time Images
JEP 221: Simplified Doclet API
JEP 222: jshell: The Java Shell (Read-Eval-Print Loop)
JEP 223: New Version-String Scheme
JEP 224: HTML5 Javadoc
JEP 225: Javadoc Search
JEP 226: UTF-8 Property Files
JEP 227: Unicode 7.0
JEP 228: Add More Diagnostic Commands
JEP 229: Create PKCS12 Keystores by Default
JEP 231: Remove Launch-Time JRE Version Selection
JEP 232: Improve Secure Application Performance
JEP 233: Generate Run-Time Compiler Tests
Automatically
JEP 235: Test Class-File Attributes Generated by javac
JEP 236: Parser API for Nashorn
JEP 237: Linux/AArch64 Port
JEP 238: Multi-Release JAR Files
JEP 240: Remove the JVM TI hprof Agent
JEP 241: Remove the jhat Tool
JEP 243: Java-Level JVM Compiler Interface
JEP 244: TLS Application-Layer Protocol Negotiation
Extension
JEP 245: Validate JVM Command-Line Flag Arguments
JEP 246: Leverage CPU Instructions for GHASH and RSA
JEP 247: Compile for Older Platform Versions
JEP 248: Make G1 the Default Garbage Collector
JEP 249: OCSP Stapling for TLS
JEP 250: Store Interned Strings in CDS Archives
JEP 251: Multi-Resolution Images
JEP 252: Use CLDR Locale Data by Default
JEP 253: Prepare JavaFX UI Controls & CSS APIs for
Modularization
JEP 254: Compact Strings
JEP 255: Merge Selected Xerces 2.11.0 Updates into
JAXP
JEP 256: BeanInfo Annotations
JEP 257: Update JavaFX/Media to Newer Version of
GStreamer
JEP 258: HarfBuzz Font-Layout Engine
JEP 259: Stack-Walking API
JEP 260: Encapsulate Most Internal APIs
JEP 261: Module System
JEP 262: TIFF Image I/O
JEP 263: HiDPI Graphics on Windows and Linux
JEP 264: Platform Logging API and Service
JEP 265: Marlin Graphics Renderer
JEP 266: More Concurrency Updates
JEP 267: Unicode 8.0
JEP 268: XML Catalogs
JEP 269: Convenience Factory Methods for Collections
JEP 270: Reserved Stack Areas for Critical Sections
JEP 271: Unified GC Logging
JEP 272: Platform-Specific Desktop Features
JEP 273: DRBG-Based SecureRandom Implementations
JEP 274: Enhanced Method Handles
JEP 275: Modular Java Application Packaging
JEP 276: Dynamic Linking of Language-Defined Object Models
JEP 277: Enhanced Deprecation
JEP 278: Additional Tests for Humongous Objects in G1
JEP 279: Improve Test-Failure Troubleshooting
JEP 280: Indify String Concatenation
JEP 281: HotSpot C++ Unit-Test Framework
JEP 282: jlink: The Java Linker
JEP 283: Enable GTK 3 on Linux
JEP 284: New HotSpot Build System
JEP 285: Spin-Wait Hints
JEP 287: SHA-3 Hash Algorithms
JEP 288: Disable SHA-1 Certificates
JEP 289: Deprecate the Applet API
JEP 290: Filter Incoming Serialization Data
JEP 291: Deprecate the Concurrent Mark Sweep (CMS)
Garbage Collector
JEP 292: Implement Selected ECMAScript 6 Features in
Nashorn
JEP 294: Linux/s390x Port
JEP 295: Ahead-of-Time Compilation
JEP 297: Unified arm32/arm64 Port
JEP 298: Remove Demos and Samples
JEP 299: Reorganize Documentation
Проект Jigsaw
http://openjdk.java.net/projects/jigsaw
Модуль – новая единица
инкапсуляции:
• Поля и методы объединяются в классы (class)
• Классы объединяются в пакеты (package)
• Java 9: Пакеты объединяются в модули
(module)
Причины создания Jigsaw
• Java “толстеет” со временем
• 95% разработчиков не нужны JavaFX, RMI, Corba
• Но вынуждены их тащить вместе с JRE, потому что Java в текущем
виде – это монолит
• Нужно модуляризировать JDK, чтобы пользователи могли
выбирать только те компоненты, которые им нужны
Размер JDK, MB
89
183
291
351
0
50
100
150
200
250
300
350
400
JDK 5 JDK 6 JDK 7 JDK 8
Размер JRE, MB
62
105
149
184
0
20
40
60
80
100
120
140
160
180
200
JRE 5 JRE 6 JRE 7 JRE 8
Нужно распиливать Java
на компоненты,
иначе будет как-то так
Java 8 Java 9 Java 10 Java 11
Причины создания Jigsaw
• Java “толстеет” со временем
• 95% разработчиков не нужны JavaFX, RMI, Corba
• Но вынуждены их тащить вместе с JRE, потому что Java в текущем
виде – это монолит
• Нужно модуляризировать JDK, чтобы пользователи могли
выбирать только те компоненты, которые им нужны
• Внутренние API JDK торчат наружу
• Нет надёжных механизмов их скрыть (public – значит все думают,
что их можно использовать, хотя это не так)
• Трудно развивать JDK, боясь сломать обратную совместимость
• Нужно инкапсулировать внутренние API
Примеры внутренних API JDK
• sun.misc.Unsafe
• sun.misc.Signal и sun.misc.SignalHandler
• sun.misc.Cleaner
• sun.reflect.Reflection.getCallerClass(int)
• sun.reflect.ReflectionFactory. newConstructorForSerialization
Модули в каком-то виде всегда были
в Java:
• jar-файлы
• Maven artifacts
• OSGi bundles
• JBoss modules
Maven
<project>
<groupId>com.axmor.java9demo</groupId>
<artifactId>java9demo</artifactId>
<packaging>pom</packaging>
<version>1.0-SNAPSHOT</version>
<modules>
<module>moduleA</module>
<module>moduleB</module>
</modules>
</project>
java9demo
moduleB
moduleA
<project>
...
<artifactId>moduleA</artifactId>
</project>
<project>
...
<artifactId>moduleB</artifactId>
<dependencies>
<dependency>
<groupId>com.axmor.java9demo</groupId>
<artifactId>moduleA</artifactId>
<version>1.0-SNAPSHOT</version>
</dependency>
</dependencies>
</project>
Проблемы модулей Maven:
• Существуют только в build-time:
• Java runtime ничего не знает про Maven
• Если модуль А зависит от модуля В, то модуль В всё
равно может обратиться к классам модуля А в рантайме
• Не решают проблему инкапсуляции:
• Нельзя скрыть пакеты от других модулей
• Нельзя закрыть классы для доступа через reflection
OSGi
(Open Services Gateway Initiative)
META-INF/MANIFEST.MF:
Manifest-Version: 1.0
Bundle-Localization: plugin
Bundle-RequiredExecutionEnvironment: CDC-1.0/Foundation-1.0,J2SE-1.3
Bundle-SymbolicName: org.eclipse.core.runtime; singleton:=true
Bundle-Activator: org.eclipse.core.internal.runtime.PlatformActivator
Require-Bundle: org.eclipse.osgi; visibility:=reexport,
org.eclipse.equinox.common; visibility:=reexport,
org.eclipse.core.jobs; visibility:=reexport,
org.eclipse.equinox.registry; visibility:=reexport,
org.eclipse.equinox.preferences; visibility:=reexport,
org.eclipse.core.contenttype; visibility:=reexport,
org.eclipse.core.runtime.compatibility.auth; resolution:=optional,
org.eclipse.equinox.app; visibility:=reexport
Export-Package: org.eclipse.core.internal.preferences.legacy; x-internal:=true,
org.eclipse.core.internal.runtime; x-friends:="org.eclipse.core.runtime.compatibility",
org.eclipse.core.runtime
Проблемы OSGI:
• Не решает до конца проблему инкапсуляции:
• setAccessible(true) по-прежнему работает
• Обновления бандлов на лету в реальных сценариях почти никогда не
работает:
• При апдейте Eclipse всё равно просит делать рестарт
• Один бандл <-> один classloader:
• Проблемы с загрузкой нескольких версий одного и того же бандла
• Циклические зависимости:
• Может нарушиться ожидаемый порядок активации бандлов
• Eclipse может не запуститься на не HotSpot
• С помощью OSGi нельзя модуляризовать саму JDK
OSGi
Jigsaw
Пример объявления модуля
myapp
src
org.example.myapp
Main.java
Class1.java
org.example.myapp.impl
Class2.java
Class3.java
module-info.java
// module-info.java
module org.example.myapp {
exports org.example.myapp;
requires java.base;
requires transitive com.google.common;
requires static org.slf4j;
}
org.example.myapp
com.google.commonjava.base org.slf4j
Уровни видимости в Java 1-8:
• private
• <package>
• protected
• public
Уровни видимости в Java 1-8:
• private
• <package>
• protected
• public
Уровни видимости в Java 9:
• private
• <package>
• protected
• public внутри модуля
• public для конкретных модулей
• public для всех
Запуск
Через class path (по старинке):
java -cp lib/guava-21.0.jar;myapp.jar org.example.myapp.Main
Через module path:
java --module-path lib/guava-21.0.jar;myapp.jar -m myapp
Запуск модульного приложения
Java runtime гарантирует, что:
• Все зависимости найдены
• Нет циклических зависимостей
• Нету расщеплённых пакетов (split packages)
Запуск по старинке (через -cp)
• module-info.class игнорируется
• Все ограничения игнорируются
• Циклы разрешены
• Расщеплённые пакеты разрешены
• Линейный поиск
Java 9 модули
Модульная Java
java.activation
java.base
java.compiler
java.corba
java.datatransfer
java.desktop
java.instrument
java.jnlp
java.logging
java.management
java.management.rmi
java.naming
java.prefs
java.rmi
java.scripting
java.se
java.se.ee
java.security.jgss
java.security.sasl
java.smartcardio
java.sql
java.sql.rowset
java.transaction
java.xml
java.xml.bind
java.xml.crypto
java.xml.ws
java.xml.ws.annotation
javafx.base
javafx.controls
javafx.deploy
javafx.fxml
javafx.graphics
javafx.media
javafx.swing
javafx.web
jdk.accessibility
jdk.charsets
jdk.crypto.cryptoki
jdk.crypto.ec
jdk.crypto.mscapi
jdk.deploy
jdk.deploy.controlpanel
jdk.dynalink
jdk.httpserver
jdk.incubator.httpclient
jdk.internal.le
jdk.internal.vm.ci
jdk.javaws
jdk.jdwp.agent
jdk.jfr
jdk.jsobject
jdk.localedata
jdk.management
jdk.management.agent
jdk.naming.dns
jdk.naming.rmi
jdk.net
jdk.pack
jdk.plugin
jdk.plugin.dom
jdk.plugin.server
jdk.scripting.nashorn
jdk.scripting.nashorn.shell
jdk.sctp
jdk.security.auth
jdk.security.jgss
jdk.snmp
jdk.unsupported
jdk.xml.dom
jdk.zipfs
oracle.desktop
oracle.net
module java.rmi {
requires java.logging;
exports java.rmi;
exports java.rmi.activation;
exports java.rmi.dgc;
exports java.rmi.registry;
exports java.rmi.server;
exports javax.rmi.ssl;
exports com.sun.rmi.rmid to java.base;
exports sun.rmi.registry to jdk.management.agent;
exports sun.rmi.server to
java.management.rmi, jdk.management.agent, jdk.jconsole;
exports sun.rmi.transport to
java.management.rmi, jdk.management.agent, jdk.jconsole;
uses java.rmi.server.RMIClassLoaderSpi;
}
Модуль java.se
module java.se {
requires transitive java.desktop;
requires transitive java.security.jgss;
requires transitive java.security.sasl;
requires transitive java.management;
requires transitive java.logging;
requires transitive java.datatransfer;
requires transitive java.sql.rowset;
requires transitive java.compiler;
requires transitive java.sql;
requires transitive java.naming;
requires transitive java.prefs;
requires transitive java.rmi;
requires transitive java.xml.crypto;
requires transitive java.management.rmi;
requires transitive java.xml;
requires transitive java.scripting;
requires transitive java.instrument;
}
Можно создать свой образ
jlink --module-path %JAVA_HOME%/jmods
--add-modules java.base --output myjre
Можно создать свой образ
jlink --module-path %JAVA_HOME%/jmods
--add-modules java.base --output myjre
35.81 MB!
Миграция
Миграция
org.example.myapp
java.xmljava.base
slf4j-api-1.7.25.jar
java.sql
org.example.mylib
guava-21.0.jar
logback-classic-1.2.2.jar logback-core-1.2.2.jar
module org.example.mylib {
exports org.example.mylib.package1;
exports org.example.mylib.package2;
requires java.base;
requires java.xml;
requires java.sql;
requires ???; // guava-21.0.jar
requires ???; // slf4j-api-1.7.25.jar
}
module org.example.mylib {
exports org.example.mylib.package1;
exports org.example.mylib.package2;
requires java.base;
requires java.xml;
requires java.sql;
requires ???; // guava-21.0.jar
requires ???; // slf4j-api-1.7.25.jar
}
module org.example.mylib {
exports org.example.mylib.package1;
exports org.example.mylib.package2;
requires java.base;
requires java.xml;
requires java.sql;
requires ???; // guava-21.0.jar
requires ???; // slf4j-api-1.7.25.jar
}
module org.example.mylib {
exports org.example.mylib.package1;
exports org.example.mylib.package2;
requires java.base;
requires java.xml;
requires java.sql;
requires ???; // guava-21.0.jar
requires ???; // slf4j-api-1.7.25.jar
}
java.xmljava.base java.sql
org.example.myliborg.example.myapp
com.google.common
logback.classic logback.core
slf4j.api
Но библиотеки ещё не модуляризованы
Но библиотеки ещё не модуляризованы
• Однако их всё равно можно использовать как
автоматические модули
module org.example.mylib {
exports org.example.mylib.package1;
exports org.example.mylib.package2;
requires java.base;
requires java.xml;
requires java.sql;
requires guava; // guava-21.0.jar
requires slf4j.api; // slf4j-api-1.7.25.jar
}
Автоматические модули
java.xmljava.base java.sql
org.example.myliborg.example.myapp
logback.classic
slf4j.api
logback.core
guava
Проблемы миграции
Пример #1
import javax.xml.bind.JAXBContext;
import javax.xml.bind.Marshaller;
import javax.xml.bind.annotation.XmlRootElement;
import java.io.File;
public class Example {
public static void main(String[] args) throws Exception {
JAXBContext jc = JAXBContext.newInstance(Dog.class);
Marshaller marshaller = jc.createMarshaller();
Dog dog = new Dog();
dog.name = "Doggy";
dog.age = 5;
marshaller.marshal(dog, new File("file"));
}
@XmlRootElement
public static class Dog {
@XmlElement public String name;
@XmlElement public int age;
}
}
Собираем на Java 8 и запускаем на Java 9
java -cp myapp.jar org.example.Example
Exception in thread "main" java.lang.NoClassDefFoundError: javax/xml/bind/JAXBContext
at org.example.Example.main(Example.java:12)
Caused by: java.lang.ClassNotFoundException: javax.xml.bind.JAXBContext
at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:553)
at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:185)
at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:486)
... 1 more
… и получаем:
Решение: --add-modules
java -cp myapp.jar --add-modules java.xml.bind
org.example.Example
или
java -cp myapp.jar --add-modules java.se.ee
org.example.Example
module java.se.ee {
requires transitive java.se;
requires transitive java.activation;
requires transitive java.transaction;
requires transitive java.corba;
requires transitive java.xml.bind;
requires transitive java.xml.ws;
requires transitive java.xml.ws.annotation;
}
Пример #2
import com.sun.javafx.collections.ObservableListWrapper;
import javafx.collections.ListChangeListener;
import javafx.collections.ObservableList;
import java.util.ArrayList;
public class Example {
public static void main(String[] args) throws Exception {
ObservableList<Integer> list = new ObservableListWrapper<>(new ArrayList<>());
list.addListener((ListChangeListener<Integer>) change -> {
while (change.next()) {
System.out.println(change.getAddedSize());
}
});
list.add(1);
list.addAll(2, 3);
list.addAll(4, 5, 6);
}
}
import com.sun.javafx.collections.ObservableListWrapper;
import javafx.collections.ListChangeListener;
import javafx.collections.ObservableList;
import java.util.ArrayList;
public class Example {
public static void main(String[] args) throws Exception {
ObservableList<Integer> list = new ObservableListWrapper<>(new ArrayList<>());
list.addListener((ListChangeListener<Integer>) change -> {
while (change.next()) {
System.out.println(change.getAddedSize());
}
});
list.add(1);
list.addAll(2, 3);
list.addAll(4, 5, 6);
}
}
Собираем на Java 8 и запускаем на Java 9
java -cp myapp.jar org.example.Example
Exception in thread "main" java.lang.IllegalAccessError: class org.example.Example (in unnamed
module @0x35f983a6) cannot access class com.sun.javafx.collections.ObservableListWrapper (in
module javafx.base) because module javafx.base does not export com.sun.javafx.collections to
unnamed module @0x35f983a6
at org.example.Example.main(Example.java:14)
… и получаем:
Решение: --add-exports
java -cp myapp.jar --add-exports
javafx.base/com.sun.javafx.collections=ALL-UNNAMED
org.example.Example
Пример #3
// Example.java
package org.example;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.Marshaller;
import java.io.File;
public class Example {
public static void main(String[] args) throws Exception {
JAXBContext jc = JAXBContext.newInstance(Dog.class);
Marshaller marshaller = jc.createMarshaller();
Dog dog = new Dog();
dog.setName("Doggy");
dog.setAge(5);
marshaller.marshal(dog, new File("file"));
}
}
// Dog.java
package org.example;
import javax.xml.bind.annotation.*;
@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class Dog {
@XmlElement private String name;
@XmlElement private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
// module-info.java
module myapp {
exports org.example;
requires java.se.ee;
}
// Example.java
package org.example;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.Marshaller;
import java.io.File;
public class Example {
public static void main(String[] args) throws Exception {
JAXBContext jc = JAXBContext.newInstance(Dog.class);
Marshaller marshaller = jc.createMarshaller();
Dog dog = new Dog();
dog.setName("Doggy");
dog.setAge(5);
marshaller.marshal(dog, new File("file"));
}
}
// Dog.java
package org.example;
import javax.xml.bind.annotation.*;
@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class Dog {
@XmlElement private String name;
@XmlElement private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
// module-info.java
module myapp {
exports org.example;
requires java.se.ee;
}
// Example.java
package org.example;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.Marshaller;
import java.io.File;
public class Example {
public static void main(String[] args) throws Exception {
JAXBContext jc = JAXBContext.newInstance(Dog.class);
Marshaller marshaller = jc.createMarshaller();
Dog dog = new Dog();
dog.setName("Doggy");
dog.setAge(5);
marshaller.marshal(dog, new File("file"));
}
}
// Dog.java
package org.example;
import javax.xml.bind.annotation.*;
@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class Dog {
@XmlElement private String name;
@XmlElement private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
// module-info.java
module myapp {
exports org.example;
requires java.se.ee;
}
Собираем и запускаем
java --module-path myapp.jar
–m myapp/org.example.Example
… и получаем:
Exception in thread "main" java.lang.reflect.InaccessibleObjectException:
Unable to make field private java.lang.String org.example.Dog.name accessible:
module myapp does not "opens org.example" to module java.xml.bind
at java.base/java.lang.reflect.AccessibleObject.checkCanSetAccessible(AccessibleObject.java:337)
at java.base/java.lang.reflect.AccessibleObject.checkCanSetAccessible(AccessibleObject.java:281)
at java.base/java.lang.reflect.Field.checkCanSetAccessible(Field.java:175)
at java.base/java.lang.reflect.Field.setAccessible(Field.java:169)
at java.xml.bind@9-
ea/com.sun.xml.internal.bind.v2.runtime.reflect.Accessor$FieldReflection.<init>(Accessor.java:233)
InaccessibleObjectException
• В Java 9 закрытые члены классов недоступны по
умолчанию для reflection, т.е. setAccessible(true)
больше не работает
// Example.java
package org.example;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.Marshaller;
import java.io.File;
public class Example {
public static void main(String[] args) throws Exception {
JAXBContext jc = JAXBContext.newInstance(Dog.class);
Marshaller marshaller = jc.createMarshaller();
Dog dog = new Dog();
dog.setName("Doggy");
dog.setAge(5);
marshaller.marshal(dog, new File("file"));
}
}
// Dog.java
package org.example;
import javax.xml.bind.annotation.*;
@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class Dog {
@XmlElement private String name;
@XmlElement private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
// module-info.java
module myapp {
exports org.example;
opens org.example;
requires java.se.ee;
}
// Example.java
package org.example;
import javax.xml.bind.JAXBContext;
import javax.xml.bind.Marshaller;
import java.io.File;
public class Example {
public static void main(String[] args) throws Exception {
JAXBContext jc = JAXBContext.newInstance(Dog.class);
Marshaller marshaller = jc.createMarshaller();
Dog dog = new Dog();
dog.setName("Doggy");
dog.setAge(5);
marshaller.marshal(dog, new File("file"));
}
}
// Dog.java
package org.example;
import javax.xml.bind.annotation.*;
@XmlRootElement
@XmlAccessorType(XmlAccessType.FIELD)
public class Dog {
@XmlElement private String name;
@XmlElement private int age;
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public int getAge() {
return age;
}
public void setAge(int age) {
this.age = age;
}
}
// module-info.java
open module myapp {
exports org.example;
requires java.se.ee;
}
Из командной строки
java --module-path myapp.jar
--add-opens myapp/org.example=java.xml.bind
–m myapp/org.example.Example
Спасибо за внимание!
http://jdk.java.net/9

More Related Content

PPTX
Java 9 Модули. Почему не OSGi?
PDF
Java худеет. Спроси меня как. Уменьшение размера дистрибутива Java приложения...
PPTX
Клиентская Java вне браузера. Делаем нативные клиенты на Java
PPTX
JVM: краткий курс общей анатомии
PPTX
JVM: краткий курс общей анатомии, JPoint 2016 Conference Edition
PPTX
Поддержка Java 8 в Excelsior JET
PPTX
Java 8 Support at the JVM Level
PDF
Разговор про Java 9. Extended version
Java 9 Модули. Почему не OSGi?
Java худеет. Спроси меня как. Уменьшение размера дистрибутива Java приложения...
Клиентская Java вне браузера. Делаем нативные клиенты на Java
JVM: краткий курс общей анатомии
JVM: краткий курс общей анатомии, JPoint 2016 Conference Edition
Поддержка Java 8 в Excelsior JET
Java 8 Support at the JVM Level
Разговор про Java 9. Extended version

What's hot (19)

PPTX
Верификация Java байткода: когда, как, а может отключить?
PDF
Tech Talks @NSU: AOT-компиляция Java
PDF
Никита Липский и Владимир Парфиненко
PDF
Continuousdelivery
ODP
Java 9 - Back to the Future
PDF
Jiramania презентации @augspb
PDF
Java худеет. Спроси меня как.
PDF
Toggle your app 2.0 (AppsConf)
PPTX
Kubernetes
PDF
Moscow Jenkins Meetup #1. Pipeline для инженеров. Обзор экосистемы
PDF
09 - Java. Тестирование Java-программ
PDF
Введение в maven
PDF
Phalcon. Что нового?
PDF
CD with Jenkins. Lessons Learned
PDF
Елизавета Голенок Переходим на mono или как это было
PDF
Иван Крутов - Автоматизация сборки Java-проекта
PDF
"Доклад не про React", Антон Виноградов, MoscowJS 27
PPTX
. Kotlin для Автоматизации тестирования – первые впечатления
PPTX
Мастер класс- Maven + Jenkins
Верификация Java байткода: когда, как, а может отключить?
Tech Talks @NSU: AOT-компиляция Java
Никита Липский и Владимир Парфиненко
Continuousdelivery
Java 9 - Back to the Future
Jiramania презентации @augspb
Java худеет. Спроси меня как.
Toggle your app 2.0 (AppsConf)
Kubernetes
Moscow Jenkins Meetup #1. Pipeline для инженеров. Обзор экосистемы
09 - Java. Тестирование Java-программ
Введение в maven
Phalcon. Что нового?
CD with Jenkins. Lessons Learned
Елизавета Голенок Переходим на mono или как это было
Иван Крутов - Автоматизация сборки Java-проекта
"Доклад не про React", Антон Виноградов, MoscowJS 27
. Kotlin для Автоматизации тестирования – первые впечатления
Мастер класс- Maven + Jenkins
Ad

Similar to Java 9 модули (20)

PDF
What to expect from Java 9
PPTX
Java 9: Platform
PDF
IT-инфраструктура. FAQ для разработчика
PPTX
JavaScript-модули "из прошлого в будущее"
PDF
Frontend: Путешествие в мир модульных загрузчиков
PDF
Java осень 2014 занятие 1
ODP
Java: вчера, сегодня, завтра
PPTX
Внедрение параллельного рендеринга в игровой движок
PDF
WebAssembly
PDF
Java/Scala Lab: Владимир Илюшенко - Jelastic PaaS v2.5 Capabilities and Benef...
PPTX
Управление облачной инфраструктурой
ODP
Java 9 - кратко о новом
PDF
SETCON'18 - Vitali Fokin - Kubernetes 101
PDF
Zero Downtime PHP Deployment with Envoyer And Forge
PDF
It meetup cd
PPTX
Net core and linux in production
PPT
RichFaces: обзор
PPTX
Uneta 17.04.15 Dekhtiar - Entity framework 7 and co.
PDF
Повышение эффективности Java приложений (новые возможности Web Logic 12c, кон...
PDF
"Webpack: 7 бед — один ответ" — Денис Измайлов, MoscowJS 17
What to expect from Java 9
Java 9: Platform
IT-инфраструктура. FAQ для разработчика
JavaScript-модули "из прошлого в будущее"
Frontend: Путешествие в мир модульных загрузчиков
Java осень 2014 занятие 1
Java: вчера, сегодня, завтра
Внедрение параллельного рендеринга в игровой движок
WebAssembly
Java/Scala Lab: Владимир Илюшенко - Jelastic PaaS v2.5 Capabilities and Benef...
Управление облачной инфраструктурой
Java 9 - кратко о новом
SETCON'18 - Vitali Fokin - Kubernetes 101
Zero Downtime PHP Deployment with Envoyer And Forge
It meetup cd
Net core and linux in production
RichFaces: обзор
Uneta 17.04.15 Dekhtiar - Entity framework 7 and co.
Повышение эффективности Java приложений (новые возможности Web Logic 12c, кон...
"Webpack: 7 бед — один ответ" — Денис Измайлов, MoscowJS 17
Ad

More from Zheka Kozlov (8)

PPTX
Модули в Java
PPTX
Вещи в Java, о которых вы (возможно) не знали
PDF
Введение в Scalaz
PDF
Интерпретирование языков с помощью Free-монад
PPTX
Введение в Akka
PPTX
PPTX
Сервис MobiBarC
PPTX
Устойчивый к искажениям алгоритм распознавания штрих-кода EAN-13
Модули в Java
Вещи в Java, о которых вы (возможно) не знали
Введение в Scalaz
Интерпретирование языков с помощью Free-монад
Введение в Akka
Сервис MobiBarC
Устойчивый к искажениям алгоритм распознавания штрих-кода EAN-13

Java 9 модули

  • 1. Java 9 модули Евгений Козлов, 19.05.2017
  • 2. История версий Java Версия Дата выхода Главные изменения Java 1.4 06.02.2002 assert, NIO Java 1.5 30.09.2004 enum, generics, annotations Java 1.6 11.12.2006 @Override in interfaces, Deque Java 1.7 07.07.2011 invokedynamic, try-with-resources Java 1.8 18.03.2014 lambdas, default methods, Nashorn Java 9 27.07.2017 modules, iface private methods, jshell
  • 4. JDK 9 JEP 102: Process API Updates JEP 110: HTTP 2 Client JEP 143: Improve Contended Locking JEP 158: Unified JVM Logging JEP 165: Compiler Control JEP 193: Variable Handles JEP 197: Segmented Code Cache JEP 199: Smart Java Compilation, Phase Two JEP 200: The Modular JDK JEP 201: Modular Source Code JEP 211: Elide Deprecation Warnings on Import Statements JEP 212: Resolve Lint and Doclint Warnings JEP 213: Milling Project Coin JEP 214: Remove GC Combinations Deprecated in JDK 8 JEP 215: Tiered Attribution for javac JEP 216: Process Import Statements Correctly JEP 217: Annotations Pipeline 2.0 JEP 219: Datagram Transport Layer Security (DTLS) JEP 220: Modular Run-Time Images JEP 221: Simplified Doclet API JEP 222: jshell: The Java Shell (Read-Eval-Print Loop) JEP 223: New Version-String Scheme JEP 224: HTML5 Javadoc JEP 225: Javadoc Search JEP 226: UTF-8 Property Files JEP 227: Unicode 7.0 JEP 228: Add More Diagnostic Commands JEP 229: Create PKCS12 Keystores by Default JEP 231: Remove Launch-Time JRE Version Selection JEP 232: Improve Secure Application Performance JEP 233: Generate Run-Time Compiler Tests Automatically JEP 235: Test Class-File Attributes Generated by javac JEP 236: Parser API for Nashorn JEP 237: Linux/AArch64 Port JEP 238: Multi-Release JAR Files JEP 240: Remove the JVM TI hprof Agent JEP 241: Remove the jhat Tool JEP 243: Java-Level JVM Compiler Interface JEP 244: TLS Application-Layer Protocol Negotiation Extension JEP 245: Validate JVM Command-Line Flag Arguments JEP 246: Leverage CPU Instructions for GHASH and RSA JEP 247: Compile for Older Platform Versions JEP 248: Make G1 the Default Garbage Collector JEP 249: OCSP Stapling for TLS JEP 250: Store Interned Strings in CDS Archives JEP 251: Multi-Resolution Images JEP 252: Use CLDR Locale Data by Default JEP 253: Prepare JavaFX UI Controls & CSS APIs for Modularization JEP 254: Compact Strings JEP 255: Merge Selected Xerces 2.11.0 Updates into JAXP JEP 256: BeanInfo Annotations JEP 257: Update JavaFX/Media to Newer Version of GStreamer JEP 258: HarfBuzz Font-Layout Engine JEP 259: Stack-Walking API JEP 260: Encapsulate Most Internal APIs JEP 261: Module System JEP 262: TIFF Image I/O JEP 263: HiDPI Graphics on Windows and Linux JEP 264: Platform Logging API and Service JEP 265: Marlin Graphics Renderer JEP 266: More Concurrency Updates JEP 267: Unicode 8.0 JEP 268: XML Catalogs JEP 269: Convenience Factory Methods for Collections JEP 270: Reserved Stack Areas for Critical Sections JEP 271: Unified GC Logging JEP 272: Platform-Specific Desktop Features JEP 273: DRBG-Based SecureRandom Implementations JEP 274: Enhanced Method Handles JEP 275: Modular Java Application Packaging JEP 276: Dynamic Linking of Language-Defined Object Models JEP 277: Enhanced Deprecation JEP 278: Additional Tests for Humongous Objects in G1 JEP 279: Improve Test-Failure Troubleshooting JEP 280: Indify String Concatenation JEP 281: HotSpot C++ Unit-Test Framework JEP 282: jlink: The Java Linker JEP 283: Enable GTK 3 on Linux JEP 284: New HotSpot Build System JEP 285: Spin-Wait Hints JEP 287: SHA-3 Hash Algorithms JEP 288: Disable SHA-1 Certificates JEP 289: Deprecate the Applet API JEP 290: Filter Incoming Serialization Data JEP 291: Deprecate the Concurrent Mark Sweep (CMS) Garbage Collector JEP 292: Implement Selected ECMAScript 6 Features in Nashorn JEP 294: Linux/s390x Port JEP 295: Ahead-of-Time Compilation JEP 297: Unified arm32/arm64 Port JEP 298: Remove Demos and Samples JEP 299: Reorganize Documentation
  • 6. Модуль – новая единица инкапсуляции: • Поля и методы объединяются в классы (class) • Классы объединяются в пакеты (package) • Java 9: Пакеты объединяются в модули (module)
  • 7. Причины создания Jigsaw • Java “толстеет” со временем • 95% разработчиков не нужны JavaFX, RMI, Corba • Но вынуждены их тащить вместе с JRE, потому что Java в текущем виде – это монолит • Нужно модуляризировать JDK, чтобы пользователи могли выбирать только те компоненты, которые им нужны
  • 10. Нужно распиливать Java на компоненты, иначе будет как-то так
  • 11. Java 8 Java 9 Java 10 Java 11
  • 12. Причины создания Jigsaw • Java “толстеет” со временем • 95% разработчиков не нужны JavaFX, RMI, Corba • Но вынуждены их тащить вместе с JRE, потому что Java в текущем виде – это монолит • Нужно модуляризировать JDK, чтобы пользователи могли выбирать только те компоненты, которые им нужны • Внутренние API JDK торчат наружу • Нет надёжных механизмов их скрыть (public – значит все думают, что их можно использовать, хотя это не так) • Трудно развивать JDK, боясь сломать обратную совместимость • Нужно инкапсулировать внутренние API
  • 13. Примеры внутренних API JDK • sun.misc.Unsafe • sun.misc.Signal и sun.misc.SignalHandler • sun.misc.Cleaner • sun.reflect.Reflection.getCallerClass(int) • sun.reflect.ReflectionFactory. newConstructorForSerialization
  • 14. Модули в каком-то виде всегда были в Java: • jar-файлы • Maven artifacts • OSGi bundles • JBoss modules
  • 15. Maven
  • 17. Проблемы модулей Maven: • Существуют только в build-time: • Java runtime ничего не знает про Maven • Если модуль А зависит от модуля В, то модуль В всё равно может обратиться к классам модуля А в рантайме • Не решают проблему инкапсуляции: • Нельзя скрыть пакеты от других модулей • Нельзя закрыть классы для доступа через reflection
  • 19. META-INF/MANIFEST.MF: Manifest-Version: 1.0 Bundle-Localization: plugin Bundle-RequiredExecutionEnvironment: CDC-1.0/Foundation-1.0,J2SE-1.3 Bundle-SymbolicName: org.eclipse.core.runtime; singleton:=true Bundle-Activator: org.eclipse.core.internal.runtime.PlatformActivator Require-Bundle: org.eclipse.osgi; visibility:=reexport, org.eclipse.equinox.common; visibility:=reexport, org.eclipse.core.jobs; visibility:=reexport, org.eclipse.equinox.registry; visibility:=reexport, org.eclipse.equinox.preferences; visibility:=reexport, org.eclipse.core.contenttype; visibility:=reexport, org.eclipse.core.runtime.compatibility.auth; resolution:=optional, org.eclipse.equinox.app; visibility:=reexport Export-Package: org.eclipse.core.internal.preferences.legacy; x-internal:=true, org.eclipse.core.internal.runtime; x-friends:="org.eclipse.core.runtime.compatibility", org.eclipse.core.runtime
  • 20. Проблемы OSGI: • Не решает до конца проблему инкапсуляции: • setAccessible(true) по-прежнему работает • Обновления бандлов на лету в реальных сценариях почти никогда не работает: • При апдейте Eclipse всё равно просит делать рестарт • Один бандл <-> один classloader: • Проблемы с загрузкой нескольких версий одного и того же бандла • Циклические зависимости: • Может нарушиться ожидаемый порядок активации бандлов • Eclipse может не запуститься на не HotSpot • С помощью OSGi нельзя модуляризовать саму JDK
  • 22. Пример объявления модуля myapp src org.example.myapp Main.java Class1.java org.example.myapp.impl Class2.java Class3.java module-info.java // module-info.java module org.example.myapp { exports org.example.myapp; requires java.base; requires transitive com.google.common; requires static org.slf4j; }
  • 24. Уровни видимости в Java 1-8: • private • <package> • protected • public
  • 25. Уровни видимости в Java 1-8: • private • <package> • protected • public Уровни видимости в Java 9: • private • <package> • protected • public внутри модуля • public для конкретных модулей • public для всех
  • 26. Запуск Через class path (по старинке): java -cp lib/guava-21.0.jar;myapp.jar org.example.myapp.Main Через module path: java --module-path lib/guava-21.0.jar;myapp.jar -m myapp
  • 27. Запуск модульного приложения Java runtime гарантирует, что: • Все зависимости найдены • Нет циклических зависимостей • Нету расщеплённых пакетов (split packages)
  • 28. Запуск по старинке (через -cp) • module-info.class игнорируется • Все ограничения игнорируются • Циклы разрешены • Расщеплённые пакеты разрешены • Линейный поиск
  • 30. Модульная Java java.activation java.base java.compiler java.corba java.datatransfer java.desktop java.instrument java.jnlp java.logging java.management java.management.rmi java.naming java.prefs java.rmi java.scripting java.se java.se.ee java.security.jgss java.security.sasl java.smartcardio java.sql java.sql.rowset java.transaction java.xml java.xml.bind java.xml.crypto java.xml.ws java.xml.ws.annotation javafx.base javafx.controls javafx.deploy javafx.fxml javafx.graphics javafx.media javafx.swing javafx.web jdk.accessibility jdk.charsets jdk.crypto.cryptoki jdk.crypto.ec jdk.crypto.mscapi jdk.deploy jdk.deploy.controlpanel jdk.dynalink jdk.httpserver jdk.incubator.httpclient jdk.internal.le jdk.internal.vm.ci jdk.javaws jdk.jdwp.agent jdk.jfr jdk.jsobject jdk.localedata jdk.management jdk.management.agent jdk.naming.dns jdk.naming.rmi jdk.net jdk.pack jdk.plugin jdk.plugin.dom jdk.plugin.server jdk.scripting.nashorn jdk.scripting.nashorn.shell jdk.sctp jdk.security.auth jdk.security.jgss jdk.snmp jdk.unsupported jdk.xml.dom jdk.zipfs oracle.desktop oracle.net
  • 31. module java.rmi { requires java.logging; exports java.rmi; exports java.rmi.activation; exports java.rmi.dgc; exports java.rmi.registry; exports java.rmi.server; exports javax.rmi.ssl; exports com.sun.rmi.rmid to java.base; exports sun.rmi.registry to jdk.management.agent; exports sun.rmi.server to java.management.rmi, jdk.management.agent, jdk.jconsole; exports sun.rmi.transport to java.management.rmi, jdk.management.agent, jdk.jconsole; uses java.rmi.server.RMIClassLoaderSpi; }
  • 32. Модуль java.se module java.se { requires transitive java.desktop; requires transitive java.security.jgss; requires transitive java.security.sasl; requires transitive java.management; requires transitive java.logging; requires transitive java.datatransfer; requires transitive java.sql.rowset; requires transitive java.compiler; requires transitive java.sql; requires transitive java.naming; requires transitive java.prefs; requires transitive java.rmi; requires transitive java.xml.crypto; requires transitive java.management.rmi; requires transitive java.xml; requires transitive java.scripting; requires transitive java.instrument; }
  • 33. Можно создать свой образ jlink --module-path %JAVA_HOME%/jmods --add-modules java.base --output myjre
  • 34. Можно создать свой образ jlink --module-path %JAVA_HOME%/jmods --add-modules java.base --output myjre 35.81 MB!
  • 37. module org.example.mylib { exports org.example.mylib.package1; exports org.example.mylib.package2; requires java.base; requires java.xml; requires java.sql; requires ???; // guava-21.0.jar requires ???; // slf4j-api-1.7.25.jar }
  • 38. module org.example.mylib { exports org.example.mylib.package1; exports org.example.mylib.package2; requires java.base; requires java.xml; requires java.sql; requires ???; // guava-21.0.jar requires ???; // slf4j-api-1.7.25.jar }
  • 39. module org.example.mylib { exports org.example.mylib.package1; exports org.example.mylib.package2; requires java.base; requires java.xml; requires java.sql; requires ???; // guava-21.0.jar requires ???; // slf4j-api-1.7.25.jar }
  • 40. module org.example.mylib { exports org.example.mylib.package1; exports org.example.mylib.package2; requires java.base; requires java.xml; requires java.sql; requires ???; // guava-21.0.jar requires ???; // slf4j-api-1.7.25.jar }
  • 42. Но библиотеки ещё не модуляризованы • Однако их всё равно можно использовать как автоматические модули
  • 43. module org.example.mylib { exports org.example.mylib.package1; exports org.example.mylib.package2; requires java.base; requires java.xml; requires java.sql; requires guava; // guava-21.0.jar requires slf4j.api; // slf4j-api-1.7.25.jar }
  • 47. import javax.xml.bind.JAXBContext; import javax.xml.bind.Marshaller; import javax.xml.bind.annotation.XmlRootElement; import java.io.File; public class Example { public static void main(String[] args) throws Exception { JAXBContext jc = JAXBContext.newInstance(Dog.class); Marshaller marshaller = jc.createMarshaller(); Dog dog = new Dog(); dog.name = "Doggy"; dog.age = 5; marshaller.marshal(dog, new File("file")); } @XmlRootElement public static class Dog { @XmlElement public String name; @XmlElement public int age; } }
  • 48. Собираем на Java 8 и запускаем на Java 9 java -cp myapp.jar org.example.Example Exception in thread "main" java.lang.NoClassDefFoundError: javax/xml/bind/JAXBContext at org.example.Example.main(Example.java:12) Caused by: java.lang.ClassNotFoundException: javax.xml.bind.JAXBContext at java.base/jdk.internal.loader.BuiltinClassLoader.loadClass(BuiltinClassLoader.java:553) at java.base/jdk.internal.loader.ClassLoaders$AppClassLoader.loadClass(ClassLoaders.java:185) at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:486) ... 1 more … и получаем:
  • 49. Решение: --add-modules java -cp myapp.jar --add-modules java.xml.bind org.example.Example или java -cp myapp.jar --add-modules java.se.ee org.example.Example
  • 50. module java.se.ee { requires transitive java.se; requires transitive java.activation; requires transitive java.transaction; requires transitive java.corba; requires transitive java.xml.bind; requires transitive java.xml.ws; requires transitive java.xml.ws.annotation; }
  • 52. import com.sun.javafx.collections.ObservableListWrapper; import javafx.collections.ListChangeListener; import javafx.collections.ObservableList; import java.util.ArrayList; public class Example { public static void main(String[] args) throws Exception { ObservableList<Integer> list = new ObservableListWrapper<>(new ArrayList<>()); list.addListener((ListChangeListener<Integer>) change -> { while (change.next()) { System.out.println(change.getAddedSize()); } }); list.add(1); list.addAll(2, 3); list.addAll(4, 5, 6); } }
  • 53. import com.sun.javafx.collections.ObservableListWrapper; import javafx.collections.ListChangeListener; import javafx.collections.ObservableList; import java.util.ArrayList; public class Example { public static void main(String[] args) throws Exception { ObservableList<Integer> list = new ObservableListWrapper<>(new ArrayList<>()); list.addListener((ListChangeListener<Integer>) change -> { while (change.next()) { System.out.println(change.getAddedSize()); } }); list.add(1); list.addAll(2, 3); list.addAll(4, 5, 6); } }
  • 54. Собираем на Java 8 и запускаем на Java 9 java -cp myapp.jar org.example.Example Exception in thread "main" java.lang.IllegalAccessError: class org.example.Example (in unnamed module @0x35f983a6) cannot access class com.sun.javafx.collections.ObservableListWrapper (in module javafx.base) because module javafx.base does not export com.sun.javafx.collections to unnamed module @0x35f983a6 at org.example.Example.main(Example.java:14) … и получаем:
  • 55. Решение: --add-exports java -cp myapp.jar --add-exports javafx.base/com.sun.javafx.collections=ALL-UNNAMED org.example.Example
  • 57. // Example.java package org.example; import javax.xml.bind.JAXBContext; import javax.xml.bind.Marshaller; import java.io.File; public class Example { public static void main(String[] args) throws Exception { JAXBContext jc = JAXBContext.newInstance(Dog.class); Marshaller marshaller = jc.createMarshaller(); Dog dog = new Dog(); dog.setName("Doggy"); dog.setAge(5); marshaller.marshal(dog, new File("file")); } } // Dog.java package org.example; import javax.xml.bind.annotation.*; @XmlRootElement @XmlAccessorType(XmlAccessType.FIELD) public class Dog { @XmlElement private String name; @XmlElement private int age; public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } } // module-info.java module myapp { exports org.example; requires java.se.ee; }
  • 58. // Example.java package org.example; import javax.xml.bind.JAXBContext; import javax.xml.bind.Marshaller; import java.io.File; public class Example { public static void main(String[] args) throws Exception { JAXBContext jc = JAXBContext.newInstance(Dog.class); Marshaller marshaller = jc.createMarshaller(); Dog dog = new Dog(); dog.setName("Doggy"); dog.setAge(5); marshaller.marshal(dog, new File("file")); } } // Dog.java package org.example; import javax.xml.bind.annotation.*; @XmlRootElement @XmlAccessorType(XmlAccessType.FIELD) public class Dog { @XmlElement private String name; @XmlElement private int age; public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } } // module-info.java module myapp { exports org.example; requires java.se.ee; }
  • 59. // Example.java package org.example; import javax.xml.bind.JAXBContext; import javax.xml.bind.Marshaller; import java.io.File; public class Example { public static void main(String[] args) throws Exception { JAXBContext jc = JAXBContext.newInstance(Dog.class); Marshaller marshaller = jc.createMarshaller(); Dog dog = new Dog(); dog.setName("Doggy"); dog.setAge(5); marshaller.marshal(dog, new File("file")); } } // Dog.java package org.example; import javax.xml.bind.annotation.*; @XmlRootElement @XmlAccessorType(XmlAccessType.FIELD) public class Dog { @XmlElement private String name; @XmlElement private int age; public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } } // module-info.java module myapp { exports org.example; requires java.se.ee; }
  • 60. Собираем и запускаем java --module-path myapp.jar –m myapp/org.example.Example … и получаем: Exception in thread "main" java.lang.reflect.InaccessibleObjectException: Unable to make field private java.lang.String org.example.Dog.name accessible: module myapp does not "opens org.example" to module java.xml.bind at java.base/java.lang.reflect.AccessibleObject.checkCanSetAccessible(AccessibleObject.java:337) at java.base/java.lang.reflect.AccessibleObject.checkCanSetAccessible(AccessibleObject.java:281) at java.base/java.lang.reflect.Field.checkCanSetAccessible(Field.java:175) at java.base/java.lang.reflect.Field.setAccessible(Field.java:169) at java.xml.bind@9- ea/com.sun.xml.internal.bind.v2.runtime.reflect.Accessor$FieldReflection.<init>(Accessor.java:233)
  • 61. InaccessibleObjectException • В Java 9 закрытые члены классов недоступны по умолчанию для reflection, т.е. setAccessible(true) больше не работает
  • 62. // Example.java package org.example; import javax.xml.bind.JAXBContext; import javax.xml.bind.Marshaller; import java.io.File; public class Example { public static void main(String[] args) throws Exception { JAXBContext jc = JAXBContext.newInstance(Dog.class); Marshaller marshaller = jc.createMarshaller(); Dog dog = new Dog(); dog.setName("Doggy"); dog.setAge(5); marshaller.marshal(dog, new File("file")); } } // Dog.java package org.example; import javax.xml.bind.annotation.*; @XmlRootElement @XmlAccessorType(XmlAccessType.FIELD) public class Dog { @XmlElement private String name; @XmlElement private int age; public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } } // module-info.java module myapp { exports org.example; opens org.example; requires java.se.ee; }
  • 63. // Example.java package org.example; import javax.xml.bind.JAXBContext; import javax.xml.bind.Marshaller; import java.io.File; public class Example { public static void main(String[] args) throws Exception { JAXBContext jc = JAXBContext.newInstance(Dog.class); Marshaller marshaller = jc.createMarshaller(); Dog dog = new Dog(); dog.setName("Doggy"); dog.setAge(5); marshaller.marshal(dog, new File("file")); } } // Dog.java package org.example; import javax.xml.bind.annotation.*; @XmlRootElement @XmlAccessorType(XmlAccessType.FIELD) public class Dog { @XmlElement private String name; @XmlElement private int age; public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } } // module-info.java open module myapp { exports org.example; requires java.se.ee; }
  • 64. Из командной строки java --module-path myapp.jar --add-opens myapp/org.example=java.xml.bind –m myapp/org.example.Example