Царев А.Java SE 9. Module system.pptx
- Количество слайдов: 37
Java SE 9 Царёв Александр AATsarev. SBT@sberbank. ru
О чём § Часть нововведений Java SE 9 § § § Приватные методы в интерфейса JShell Улучшенный try-with-resources API Реактивного программирования Diamond оператор для анонимных классов Разное § Java Platform Module System – JPMS § Полный список openjdk. java. net/projects/jdk 9/ 2
Это Interface или … ? § Java 7 и ранее – простое описание контракта public interface DBLogging{ String MONGO_DB_NAME = "ABC_Mongo_Datastore"; String NEO 4 J_DB_NAME = "ABC_Neo 4 J_Datastore"; String CASSANDRA_DB_NAME = "ABC_Cassandra_Datastore"; void log. Info(String message); void log. Warn(String message); } 3
Это Interface или … ? § Java 8 – default и static методы (публичные) public interface DBLogging{ String MONGO_DB_NAME = "ABC_Mongo_Datastore"; String NEO 4 J_DB_NAME = "ABC_Neo 4 J_Datastore"; String CASSANDRA_DB_NAME = "ABC_Cassandra_Datastore"; default void log. Info(String message){ // Step 1: Connect to Data. Store // Setp 2: Log Info Message // Setp 3: Close the Data. Store connection } default void log. Warn(String message){ // Step 1: Connect to Data. Store // Setp 2: Log Warn Message // Setp 3: Close the Data. Store connection } public static String format(String format, String message) { return String. format(format, message); } // Any other abstract methods } 4
Это Interface или … ? § Java 9 – private методы public interface DBLogging{ String MONGO_DB_NAME = "ABC_Mongo_Datastore"; String NEO 4 J_DB_NAME = "ABC_Neo 4 J_Datastore"; String CASSANDRA_DB_NAME = "ABC_Cassandra_Datastore"; default void log. Info(String message){ log(message, "INFO") } default void log. Warn(String message){ log(message, "WARN") } private void log(String message, String msg. Prefix){ // Step 1: Connect to Data. Store // Setp 2: Log Message with Prefix and styles etc. // Setp 3: Close the Data. Store connection } public static String format(String format, String message) { return String. format(format, message); } // Any other abstract methods } 5
JShell § § REPL – read-eval-print loop Используется для тестирования и использования в консоли разных конструкций, классов, интерфейсов, перечислений, объектов, операторов и т. д. 6
JShell import jdk. jshell. JShell; import jdk. jshell. Snippet. Event; import java. util. List; public class JShell. Test { public static void main(String[] args) { JShell. Builder builder = JShell. builder(); JShell build = builder. build(); List<Snippet. Event> eval = build. eval("System. out. println("1 + 1 = " + (1 + 1)); "); eval. for. Each(event -> System. out. println(event. value())); eval = build. eval(“System. exit(-123); "); eval. for. Each(event -> System. out. println(event. value())); } } Output: 1 + 1 = 2 null Process finished with exit code 0 7
try-with-resources § Добавлен синтаксический сахар static void java 7() throws IOException { Buffered. Reader reader 1 = new Buffered. Reader(new File. Reader("1. txt")); try (Buffered. Reader reader 2 = reader 1) { System. out. println(reader 2. read. Line()); } } static void java 9() throws IOException { Buffered. Reader reader 1 = new Buffered. Reader(new File. Reader("1. txt")); try (reader 1) { System. out. println(reader 1. read. Line()); } } 8
try-with-resources static void java 7() throws IOException { Buffered. Reader reader 1 = new Buffered. Reader(new File. Reader("1. txt")); Buffered. Reader reader 2 = reader 1 ; Throwable var 2 = null; try { System. out. println(reader 2. read. Line()) ; } catch (Throwable var 7) { var 2 = var 7; throw var 7; } finally { if(reader 1 != null) { $close. Resource(var 2 , reader 1); } } } static void java 9() throws IOException { Buffered. Reader reader 1 = new Buffered. Reader(new File. Reader("1. txt")); Throwable var 2 = null; try { System. out. println(reader 1. read. Line()) ; } catch (Throwable var 7) { var 2 = var 7; throw var 7; } finally { if(reader 1 != null) { $close. Resource(var 2 , reader 1); } } } 9
Реактивное программирование • В Scala, Akka уже были интегрированы reactive streams. • Oracle решила добавить Reactive Streams API в Java SE 9. • Java SE 9 Reactive Streams API — фреймворк для реализации асинхронных, масштабируемых и параллельных приложений с использованием Java. • В Java SE 9 появятся следующие API: • java. util. concurrent. Flow; • java. util. concurrent. Flow. Publisher; • java. util. concurrent. Flow. Subscriber; • java. util. concurrent. Flow. Processor. • Реализация: • java. util. concurrent. Submission. Publisher – базовая реализация 10
Diamond для анонимных классов <T> Box<T> create. Box(T content) { // Нужно поставить 'T' здесь : ( return new Box<T>(content) { }; } Разве не очевидно, что Box должен быть типа T? Проблема в не обозначаемых (англ. non-denotable) типах, которые распознаются компилятором, а JVM — нет. (Такой случай может быть обработан компилятором, но вопрос — как корректно передать его JVM. ) Проблему исправили в Java 9: Предположим, что у нас есть класс Box<T> и мы хотим сделать его анонимным. Вот как это выглядит в Java 8: <T> Box<T> create. Box(T content) { // Java 9 выводит ‘T’, потому что этот тип обозначаемый return new Box<>(content) { }; } Box<? > create. Crazy. Box(Object content) { List<? > inner. List = Arrays. as. List(content); // А этот тип не выводится, так как не можем его обозначить: // return new Box<>(inner. List) { }; // Вместо этого обозначаем тот тип, который нам нужен: return new Box<List<? >>(inner. List) { }; } 11
Разное § Immutable коллекции в JDK § API для изображений с разными разрешениями (Multi. Resolution. Image. java) § JEP 238: Multi-Release JAR Files § JEP 264: Platform Logging API and Service § JEP 277: Enhanced Deprecation § JEP 290: Filter Incoming Serialization Data § JEP 295: Ahead-of-Time Compilation 12
Java Platform Module System
Project Jigsaw • • http: //openjdk. java. net/projects/jigsaw/ Сделать Java SE Platform и JDK легче масштабируемой для мобильных устройств Улучшить безопасность и способность к поддержке платформы и JDK Сделать реализацию и поддержку библиотек и больших приложений на Java SE и EE проще 14
Мотивация • Зачем? Что было раньше плохо? § § § JEP 200: The Modular JDK JEP 201: Modular Source Code JEP 220: Modular Run-Time Images JEP 260: Encapsulate Most Internal APIs JEP 261: Module System JEP 282: jlink: The Java Linker 15
Модуль ● Логическое объединение пакетов, с дополнительной инкапсуляцией ● Целевое расширение jmod ● ● В основном, модуль – это почти то же самое что JAR файл, собранный из скомпилированных java файлов. Отличается наличием файла, описывающего модуль moduleinfo. java. Он определяет: – уникальное имя описываемого модуля – от каких модулей зависит описываемый модуль – какие пакеты экспортируются для других модулей 16
Модуль приложения • Также называются «Именованные прикладные модули» . Это то, что пишут программисты. • Чтобы использовать правильно «всю модульность» нужно, чтобы все зависимости были модулями… • Обратная совместимость и миграция: • • Автоматические модули – любой JAR, помещённый в module-path без дескриптора модуля считается автоматическим модулем, позволяя проекту использовать библиотеки ранних версий. Безымянный (Unnamed) модуль – однако class-path ещё существует. . . Все JAR файлы (модульные или нет) и классы в class-path’е будут содержаться в нём. 17
«Читабельность» модуля Module type Origin Exports packages Can read modules (Named) Platform Modules provided by JDK explicitly (Named) Application Modules any JAR containing module-info. class on the module path explicitly Platform Application Automatic Modules any JAR without module-info. class on the module path all Platform Application Automatic Unnamed Module all JARs and classes on the classpath all Platform Automatic Application • Обеспечение надежности конфигурации: • граф модулей должен быть ацикличным; • модуль читает не более одного модуля, с конкретный пакетом; • модули, определяющие одинаковые пакеты, не перекрывают друга. 18
Platform 19
JDK 20
Module-path как замена Classpath • В classpath артефакты могут: • содержать типы в одинаковых пакетах, даже если это разные версии одного типа. • теряться от момента компиляции до run-time’а • • Module-path содержит артефакты модулей. Переменная module-path содержит скомпилированные определения библиотеки и модулей приложений (все фазы жизненного цикла). Modular JAR Non-Modular JAR --module-path (-mp) --classpath (-cp) application module unnamed module automatic module unnamed module 21
module-info. java • Простейшее описание модуля с экспортируемым пакетом: module com. sbt. jre. service { exports com. sbt. jre. service; } • Вложенные пакеты в com. sbt. jre. service нужно экспортировать явно! • Если нужно экспортировать пакет конкретному стороннему модулю, то используется ограниченный экспорт: my. package to another. module • Описание зависимостей: module com. sbt. jre { requires com. sbt. jre. service; } • Часть requires ссылается только на имена пакетов. • Для транзитивного экспорта пакета com. sbt. jre. service через модуль com. sbt. jre другим модулям нужно использовать requires transitive 22
Сервисы • Чтобы обеспечить низкую связность модулей, в модульную систему зашито использование сервисов. • Пусть модуль com. sbt. jre ничего не знает о реализации, но хочет использовать сервис com. sbt. jre. service. Event. Service: module com. sbt. jre { requires com. sbt. jre. service; uses com. sbt. jre. service. Event. Service; } • Реализация сервиса поставляется отдельным модулем: module com. sbt. jre. talk. service { requires com. sbt. jre. service; exports com. sbt. jre. talk. service; provides com. sbt. jre. service. Event. Service with com. sbt. jre. talk. service. Talk. Service; } 23
Сервисы • Использование в клиентском коде: Service. Loader. load(Event. Service. class) • Возвращает перечисление Iterable<T>, в котором для данного сервиса содержатся все реализации, предлагаемые модулями из module-path и описанные в блоке provides. . . with. . . 24
Пример модуля jdk. jshell module jdk. jshell { requires transitive java. compiler; requires jdk. compiler; requires transitive java. prefs; requires jdk. internal. ed; requires java. logging; requires transitive jdk. jdi; requires jdk. internal. opt; requires jdk. internal. le; exports jdk. jshell. spi; jdk. jshell. tool; jdk. jshell. execution; uses jdk. internal. editor. spi. Build. In. Editor. Provider; uses jdk. jshell. spi. Execution. Control. Provider; provides javax. tools. Tool with jdk. internal. jshell. tool. JShell. Tool. Provider; provides jdk. jshell. spi. Execution. Control. Provider with jdk. jshell. execution. Jdi. Execution. Control. Provider, jdk. jshell. execution. Local. Execution. Control. Provider, jdk. jshell. execution. Fail. Over. Execution. Control. Provider; } 25
Всё познаётся в сравнении… Jigsaw Class-Loader OSGi Java EE (Spec) ext/lib Allows cycles between packages in different modules ✘ ✔ ✔ Isolated package namespaces ✘ ✔ ✔ ✔ ✘ Allows lazy loading ✘ ✔ ✔ Allows multiple versions of an artifact ✘ ✔ ✔ Allows split packages ✘ ✔ ✔ Module redefinition ✘ ✔ ✔ Theoretically Possible to AOTcompile ✔ ✔ ✔ 26
А как на счёт… – Module Hell? – Есть ли динамическая загрузка зависимостей? – Версионирование зависимостей? – Деплой на мобильные устройства легче? – Что с classloader’ами? – reflection — теперь нельзя то, что очень хочется? 27
Список источников ● http: //openjdk. java. net/projects/jdk 9/ ● http: //openjdk. java. net/projects/jigsaw/ ● http: //www. journaldev. com/13121/java-9 -features-with-examples ● https: //developer. jboss. org/blogs/scott. stark/2017/04/14/critical-deficiencies-in-jigsawjsr 376 -java-platform-module-system-ec-member-concerns? _sscc=t ● https: //developer. atlassian. com/blog/2015/08/optional-broken/ ● https: //dzone. com/articles/whats-wrong-java-8 -part-iv ● https: //labs. consol. de/development/2017/02/13/getting-started-with-java 9 -modules. html ● https: //blog. codefx. org/java/dev/will-there-be-module-hell/ ● http: //shop. oreilly. com/product/9781787282841. do ● http: //www. apress. com/la/book/9781484225912 28
Спасибо за внимание! 29
Приложение. Автоматические модули • • Нужен способ миграции приложений, даже если они зависят от библиотек, которые еще не были опубликованы как модули. Автоматические модули: любой JAR, помещённый в module-path без дескриптора модуля считается автоматическим модулем, позволяя вашему проекту Java 9 использовать библиотеки ранних версий. Автоматические модули неявно экспортируют все свои пакеты и имеют доступ ко всем остальным модулям. Поскольку автоматический модуль не объявляет явно имя, оно генерируется в зависимости от имени JAR файла. В основном, он удалит расширение файла и номер завершающей версии (если есть) и заменит все небуквенные символы точками, например: mongo-java-driver-3. 3. 0. jar будет выглядеть как модуль с именем mongo. java. driver (точный алгоритм описан в документации Module. Finder. Каждый модуль, который требует mongo. java. driver, имеет доступ ко всем его пакетам. Автоматические модули, в свою очередь, могут обращаться ко всем другим модулям, в том числе к безымянному модулю. 30
Приложение. Безымянный (Unnamed) модуль • Однако class-path ещё существует. . . Все JAR файлы (модульные или нет) и классы в class-path’е будут содержаться в безымянном модуле. • Подобно автоматическим модулям, он экспортирует все пакеты и читает все остальные модули. • Не имеет имени. По этой причине на него не могут ссылаться именованные модули приложения. • Безымянный модуль может получить доступ ко всем другим модулям. • Он один на JVM 31
Приложение. Платформенные модули • И последнее, но не менее важное: сама JDK была перенесена в модульную структуру. Вся основная функциональность Java будет предоставляться различными модулями, например java. xml, java. logging или java. httpclient. • Именование модулей: префиксы java. * vs jdk. * • Не считая javafx. *, oracle. * • Модуль java. base • Корневой и обязательный модуль • Самый базовый API предоставляется java. base, любой модуль зависит от него неявно. • Включает java. lang. module – работа с модульной системой 32
Приложение. Platform «изнутри» 33
Приложение. JDK «изнутри» 34
Приложение. Именование модуля • Имя модуля – так же как именуются пакеты – обратное имя домена, например: com. sbt. jre • Имя каталога, содержащего модуль, должно быть равно имени модуля. Например для сервиса com. sbt. jre. service: src +- main +- com. sbt. jre. service +- module-info. java +- com +- sbt +- jre +- service +- Event. Service. java • Технически, имя модуля не зависит от имён, располагаемых в нём пакетов. 35
Приложение. No "Current Module" Existing systems rely on identifying the current application by using the Thread Context Class Loader (TCCL). Because modules in Jigsaw are not represented by class loaders, programs which rely on this behavior of the TCCL will begin to exhibit subtly incorrect behavior. No corresponding concept exists for modules, which means that any software relying on this concept must be redesigned and re-implemented to use some different approach. 36
Reactive stream test import java. util. concurrent. Executors; import java. util. concurrent. Flow; import java. util. concurrent. Submission. Publisher; public class Reactive. Stream. Test { public static void main(String[] args) { Submission. Publisher publisher = new Submission. Publisher(Executors. new. Fixed. Thread. Pool(3), 5); publisher. subscribe(new Flow. Subscriber() { @Override public void on. Subscribe(Flow. Subscription subscription) { subscription. request(Long. MAX_VALUE); System. out. println("Subscriber#on. Subscribe: " + subscription); } @Override public void on. Next(Object item) { System. out. println("Subscriber#on. Next: " + item); } @Override public void on. Error(Throwable throwable) { System. out. println("Subscriber#on. Error: " + throwable); } @Override public void on. Complete() { System. out. println("Subscriber#on. Complete: DONE!"); } }); for (int i = 0; i < 5; i++) { System. out. println("Published " + i); publisher. submit(i); } } } 37
Царев А.Java SE 9. Module system.pptx