Slide 1

Slide 1 text

Модули в Java Евгений Козлов Встреча Novosibirsk Java User Group 24.05.2018

Slide 2

Slide 2 text

Обо мне • Программирую на Java 7 лет • Последние 5 лет в Axmor. Программирую desktop (Eclipse). • Веду Telegram-канал, посвящённый Java: https://t.me/miniJUG • Интересуюсь функциональным программированием: https://vk.com/lambdansk 2/136

Slide 3

Slide 3 text

Обо мне • Программирую на Java 7 лет • Последние 5 лет в Axmor. Программирую desktop (Eclipse). • Веду Telegram-канал, посвящённый Java: https://t.me/miniJUG • Интересуюсь функциональным программированием: https://vk.com/lambdansk • Отвечаю на StackOverflow. 3/136

Slide 4

Slide 4 text

История версий 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 21.09.2017 modules, iface private methods, jshell Java 10 20.03.2018 var, Graal 4/136

Slide 5

Slide 5 text

Java 8 5/136

Slide 6

Slide 6 text

Java 8 6/136

Slide 7

Slide 7 text

Проблемы монолитной JDK 7/136

Slide 8

Slide 8 text

Проблемы монолитной JDK • Большой размер JRE 5 184MB JRE 7 JRE 8 62MB 105MB 149MB JRE 6 8/136

Slide 9

Slide 9 text

Проблемы монолитной JDK • Большой размер • Плоская структура (запутанный граф зависимостей) rt.jar links 9/136

Slide 10

Slide 10 text

Проблемы монолитной JDK • Большой размер • Плоская структура (запутанный граф зависимостей) • Сложность разработки и поддержки 10/136

Slide 11

Slide 11 text

Проблемы монолитной JDK • Большой размер • Плоская структура (запутанный граф зависимостей) • Сложность разработки и поддержки • Медленный старт и много памяти 11/136

Slide 12

Slide 12 text

Проблемы монолитной JDK • Большой размер • Плоская структура (запутанный граф зависимостей) • Сложность разработки и поддержки • Медленный старт и много памяти • Внутренние API торчат наружу 12/136

Slide 13

Slide 13 text

Цели • Разделить JDK на компоненты и сделать платформу масштабируемой 13/136

Slide 14

Slide 14 text

Цели • Разделить JDK на компоненты и сделать платформу масштабируемой • Облегчить разработку и поддержку больших систем, в том числе самой JDK 14/136

Slide 15

Slide 15 text

Цели • Разделить JDK на компоненты и сделать платформу масштабируемой • Облегчить разработку и поддержку больших систем, в том числе самой JDK • Улучшить производительность и уменьшить потребление памяти 15/136

Slide 16

Slide 16 text

Цели • Разделить JDK на компоненты и сделать платформу масштабируемой • Облегчить разработку и поддержку больших систем, в том числе самой JDK • Улучшить производительность и уменьшить потребление памяти • Улучшить безопасность, инкапсулировать внутренние API 16/136

Slide 17

Slide 17 text

История • Всё началось в 2005 году с JSR 277: Java Module System 17/136

Slide 18

Slide 18 text

История • Всё началось в 2005 году с JSR 277: Java Module System • 2008 год – создание проекта Jigsaw 18/136

Slide 19

Slide 19 text

История • Всё началось в 2005 году с JSR 277: Java Module System • 2008 год – создание проекта Jigsaw • 2010 год – Jigsaw перенесён в Java 8 • 2012 год – Jigsaw перенесён в Java 9 19/136

Slide 20

Slide 20 text

История • Всё началось в 2005 году с JSR 277: Java Module System • 2008 год – создание проекта Jigsaw • 2010 год – Jigsaw перенесён в Java 8 • 2012 год – Jigsaw перенесён в Java 9 • 2014 год – старт фазы активной разработки Jigsaw 20/136

Slide 21

Slide 21 text

21/136

Slide 22

Slide 22 text

22/136

Slide 23

Slide 23 text

История • Всё началось в 2005 году с JSR 277: Java Module System • 2008 год – создание проекта Jigsaw • 2010 год – Jigsaw перенесён в Java 8 • 2012 год – Jigsaw перенесён в Java 9 • 2014 год – старт фазы активной разработки Jigsaw • 21.09.2017 – выход Java 9 23/136

Slide 24

Slide 24 text

Проект Jigsaw • JEP 162: Prepare for Modularization • 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 24/136

Slide 25

Slide 25 text

Java 8 rt.jar 25/136

Slide 26

Slide 26 text

Java 8 Java 9+ rt.jar lib/modules 26/136

Slide 27

Slide 27 text

Java 8 jdk1.8.0_172 ├── bin | ├── java.exe | ├── javac.exe | ├── jar.exe | └── … ├── jre | ├── bin | | ├── java.exe | | └── … | ├── lib | | ├── rt.jar | | └── … | └── … ├── lib | ├── tools.jar | └── … ├── src.zip └── … 27/136

Slide 28

Slide 28 text

Java 8 jdk1.8.0_172 ├── bin | ├── java.exe | ├── javac.exe | ├── jar.exe | └── … ├── jre | ├── bin | | ├── java.exe | | └── … | ├── lib | | ├── rt.jar | | └── … | └── … ├── lib | ├── tools.jar | └── … ├── src.zip └── … 28/136

Slide 29

Slide 29 text

Java 8 Java 9+ jdk1.8.0_172 ├── bin | ├── java.exe | ├── javac.exe | ├── jar.exe | └── … ├── jre | ├── bin | | ├── java.exe | | └── … | ├── lib | | ├── rt.jar | | └── … | └── … ├── lib | ├── tools.jar | └── … ├── src.zip └── … jdk10.0.1 ├── bin | ├── java.exe | ├── javac.exe | ├── jar.exe | └── … ├── lib | ├── modules | ├── jrt-fs.jar | ├── src.zip | └── … ├── jmods | ├── java.base.jmod | ├── java.desktop.jmod | ├── java.xml.jmod | └── … └── … 29/136

Slide 30

Slide 30 text

Java 8 Java 9+ jdk1.8.0_172 ├── bin | ├── java.exe | ├── javac.exe | ├── jar.exe | └── … ├── jre | ├── bin | | ├── java.exe | | └── … | ├── lib | | ├── rt.jar | | └── … | └── … ├── lib | ├── tools.jar | └── … ├── src.zip └── … jdk10.0.1 ├── bin | ├── java.exe | ├── javac.exe | ├── jar.exe | └── … ├── lib | ├── modules | ├── jrt-fs.jar | ├── src.zip | └── … ├── jmods | ├── java.base.jmod | ├── java.desktop.jmod | ├── java.xml.jmod | └── … └── … 30/136

Slide 31

Slide 31 text

Java 8 Java 9+ jdk1.8.0_172 ├── bin | ├── java.exe | ├── javac.exe | ├── jar.exe | └── … ├── jre | ├── bin | | ├── java.exe | | └── … | ├── lib | | ├── rt.jar | | └── … | └── … ├── lib | ├── tools.jar | └── … ├── src.zip └── … jdk10.0.1 ├── bin | ├── java.exe | ├── javac.exe | ├── jar.exe | └── … ├── lib | ├── modules | ├── jrt-fs.jar | ├── src.zip | └── … ├── jmods | ├── java.base.jmod | ├── java.desktop.jmod | ├── java.xml.jmod | └── … └── … 31/136

Slide 32

Slide 32 text

Нахождение системных модулей 32/136

Slide 33

Slide 33 text

Нахождение системных модулей FileSystem fs = FileSystems.getFileSystem(URI.create("jrt:/")); 33/136

Slide 34

Slide 34 text

Нахождение системных модулей FileSystem fs = FileSystems.getFileSystem(URI.create("jrt:/")); // Получить стрим всех модулей: Stream modules = Files.list(fs.getPath("modules")); 34/136

Slide 35

Slide 35 text

Нахождение системных модулей FileSystem fs = FileSystems.getFileSystem(URI.create("jrt:/")); // Получить стрим всех модулей: Stream modules = Files.list(fs.getPath("modules")); // Получить массив байтов файла Object.class: byte[] bytes = Files.readAllBytes(fs.getPath("modules", "java.base", "java/lang/Object.class")); 35/136

Slide 36

Slide 36 text

Java 9+ jdk10.0.1 ├── bin | ├── java.exe | ├── javac.exe | ├── jar.exe | └── … ├── lib | ├── modules | ├── jrt-fs.jar | ├── src.zip | └── … ├── jmods | ├── java.base.jmod | ├── java.desktop.jmod | ├── java.xml.jmod | └── … └── … 36/136

Slide 37

Slide 37 text

Терминология • Static access – обычный доступ к полям и методам: com.Foo.bar() 37/136

Slide 38

Slide 38 text

Терминология • Static access – обычный доступ к полям и методам: com.Foo.bar() • Reflective access – рефлективный доступ к полям и методам: Method m = Class.forName("com.Foo").getDeclaredMethod("bar"); m.invoke(null); 38/136

Slide 39

Slide 39 text

Терминология • Static access – обычный доступ к полям и методам: com.Foo.bar() • Reflective access – рефлективный доступ к полям и методам: Method m = Class.forName("com.Foo").getDeclaredMethod("bar"); m.invoke(null); • Deep reflective access – приватный рефлективный доступ к полям и методам: Method m = Class.forName("com.Foo").getDeclaredMethod("baz"); m.setAccessible(true); m.invoke(null); 39/136

Slide 40

Slide 40 text

Ага, используешь приватный API 40/136

Slide 41

Slide 41 text

Инкапсуляция внутренних API • В Java 9/10 нестандартные API стали закрыты во время компиляции, но открыты в рантайме 41/136

Slide 42

Slide 42 text

Инкапсуляция внутренних API • В Java 9/10 нестандартные API стали закрыты во время компиляции, но открыты в рантайме • Во время deep reflective access к классам JVM выдаёт предупреждение: Field field = ArrayList.class.getDeclaredField("elementData"); field.setAccessible(true); WARNING: An illegal reflective access operation has occurred WARNING: Illegal reflective access by org.example.Main (…) to field java.util.ArrayList.elementData 42/136

Slide 43

Slide 43 text

А что Unsafe? 43/136

Slide 44

Slide 44 text

Неинкапсулированные API (пока) • sun.misc.Unsafe • sun.misc.Signal и sun.misc.SignalHandler • sun.reflect.Reflection.getCallerClass(int) • sun.reflect.ReflectionFactory. newConstructorForSerialization() 44/136

Slide 45

Slide 45 text

Использует ли моё приложение внутренние API? 45/136

Slide 46

Slide 46 text

Использует ли моё приложение внутренние API? > jdeps --jdk-internals hadoop-hdfs-2.2.0.jar hadoop-hdfs-2.2.0.jar -> java.xml org.apache.hadoop.hdfs.tools.offlineEditsViewer.XmlEditsVisitor -> com.sun.org.apache.xml.internal.serialize.OutputFormat JDK internal API (java.xml) org.apache.hadoop.hdfs.tools.offlineEditsViewer.XmlEditsVisitor -> com.sun.org.apache.xml.internal.serialize.XMLSerializer JDK internal API (java.xml) Warning: JDK internal APIs are unsupported and private to JDK implementation that are subject to be removed or changed incompatibly and could break your application. Please modify your code to eliminate dependence on any JDK internal APIs. For the most recent update on JDK internal API replacements, please check: https://wiki.openjdk.java.net/display/JDK8/Java+Dependency+Analysis+Tool 46/136

Slide 47

Slide 47 text

Пример объявления модуля mylib src org.example.mylib Main.java Class1.java org.example.mylib.impl Class2.java Class3.java 47/136

Slide 48

Slide 48 text

Пример объявления модуля mylib src org.example.mylib Main.java Class1.java org.example.mylib.impl Class2.java Class3.java module-info.java // module-info.java module org.example.mylib { exports org.example.mylib; requires java.base; requires transitive com.foo; requires static com.bar; } 48/136

Slide 49

Slide 49 text

Пример объявления модуля mylib src org.example.mylib Main.java Class1.java org.example.mylib.impl Class2.java Class3.java module-info.java // module-info.java module org.example.mylib { exports org.example.mylib; requires java.base; requires transitive com.foo; requires static com.bar; } concealed package 49/136

Slide 50

Slide 50 text

java.base requires requires transitive org.example.mylib requires static com.foo com.bar 50/136

Slide 51

Slide 51 text

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; } qualified export 51/136

Slide 52

Slide 52 text

Уровни видимости в Java 1-8: • private • • protected • public 52/136

Slide 53

Slide 53 text

Уровни видимости в Java 1-8: • private • • protected • public Уровни видимости в Java 9+: • private • • protected • public внутри модуля • public для конкретных модулей • public для всех 53/136

Slide 54

Slide 54 text

module jdk.unsupported { exports com.sun.nio.file; exports sun.misc; exports sun.reflect; opens sun.misc; opens sun.reflect; } Открытые пакеты 54/136

Slide 55

Slide 55 text

module jdk.unsupported { exports com.sun.nio.file; exports sun.misc; exports sun.reflect; opens sun.misc; opens sun.reflect; } Открытые пакеты открыты для deep reflection 55/136

Slide 56

Slide 56 text

Запуск на Java 8 Через class path: java -cp foo.jar;bar.jar;myapp.jar org.example.myapp.Main 56/136

Slide 57

Slide 57 text

Запуск на Java 9+ Через class path (по старинке): java -cp foo.jar;bar.jar;myapp.jar org.example.myapp.Main Через module path: java -p foo.jar;bar.jar;myapp.jar -m org.example.myapp 57/136

Slide 58

Slide 58 text

Запуск модульного приложения Java runtime гарантирует, что: • Все зависимости найдены 58/136

Slide 59

Slide 59 text

Запуск модульного приложения Java runtime гарантирует, что: • Все зависимости найдены • Нет циклических зависимостей 59/136

Slide 60

Slide 60 text

Запуск модульного приложения Java runtime гарантирует, что: • Все зависимости найдены • Нет циклических зависимостей • Нет расщеплённых пакетов (split packages) 60/136

Slide 61

Slide 61 text

Запуск по старинке (через -cp) • module-info.class игнорируется • Все ограничения игнорируются • Циклы разрешены • Расщеплённые пакеты разрешены • Линейный поиск 61/136

Slide 62

Slide 62 text

-cp target\classes; libs\com\google\guava\guava\25.0-jre\guava-25.0-jre.jar; libs\org\checkerframework\checker-compat- qual\2.0.0\checker-compat-qual-2.0.0.jar; libs\com\google\errorprone\error_prone_annotations\2.1.3\ error_prone_annotations-2.1.3.jar; libs\com\google\j2objc\j2objc-annotations\1.1\j2objc- annotations-1.1.jar; libs\org\codehaus\mojo\animal-sniffer- annotations\1.14\animal-sniffer-annotations-1.14.jar 62/136

Slide 63

Slide 63 text

63/136

Slide 64

Slide 64 text

--module-path -classpath 64/136

Slide 65

Slide 65 text

Аналоги директив в опциях VM и runtime 65/136

Slide 66

Slide 66 text

Аналоги директив в опциях VM и reflection module-info.java VM option java.lang.Module module foo { requires bar; } --add-reads foo=bar foo.addReads(bar) 66/136

Slide 67

Slide 67 text

Аналоги директив в опциях VM и reflection module-info.java VM option java.lang.Module module foo { requires bar; } --add-reads foo=bar foo.addReads(bar) module foo { exports com.foo to bar; } --add-exports foo/com.foo=bar foo.addExports("com.foo", bar) 67/136

Slide 68

Slide 68 text

Аналоги директив в опциях VM и reflection module-info.java VM option java.lang.Module module foo { requires bar; } --add-reads foo=bar foo.addReads(bar) module foo { exports com.foo to bar; } --add-exports foo/com.foo=bar foo.addExports("com.foo", bar) module foo { opens com.foo to bar; } --add-opens foo/com.foo=bar foo.addOpens("com.foo", bar) 68/136

Slide 69

Slide 69 text

Граф модулей java.xml foo java.base baz qux bar java.prefs 69/136

Slide 70

Slide 70 text

java -p foo.jar;bar.jar;qux.jar;baz.jar -m foo Граф модулей 70/136

Slide 71

Slide 71 text

Граф модулей java.xml foo java.base корневой модуль (root) baz qux bar java.prefs 71/136

Slide 72

Slide 72 text

Граф модулей java.xml foo java.base корневой модуль (root) baz qux bar java.prefs 72/136

Slide 73

Slide 73 text

Граф модулей java.xml foo java.base корневой модуль (root) baz qux bar java.prefs 73/136

Slide 74

Slide 74 text

java -p foo.jar;bar.jar;qux.jar;baz.jar -m foo Добавление модулей в корневое множество 74/136

Slide 75

Slide 75 text

Добавление модулей в корневое множество java -p foo.jar;bar.jar;qux.jar;baz.jar --add-modules baz -m foo 75/136

Slide 76

Slide 76 text

Граф модулей java.xml foo baz java.prefs bar java.base qux корневой модуль (root) корневой модуль (root) 76/136

Slide 77

Slide 77 text

Виды модулей Module 77/136

Slide 78

Slide 78 text

Виды модулей Module Unnamed Named 78/136

Slide 79

Slide 79 text

Виды модулей Module Unnamed Automatic Explicit Named 79/136

Slide 80

Slide 80 text

Виды модулей Module Unnamed Automatic Explicit System Named 80/136

Slide 81

Slide 81 text

Кроме того, системные модули могут быть: • Aggregator (например, java.se) 81/136

Slide 82

Slide 82 text

Модуль 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; } 82/136

Slide 83

Slide 83 text

Кроме того, системные модули могут быть: • Aggregator (например, java.se) • Deprecated и Deprecated for removal (например, java.se.ee) 83/136

Slide 84

Slide 84 text

Модуль java.se.ee @Deprecated(since="9", forRemoval=true) module java.se.ee { requires transitive java.se; requires transitive java.activation; requires transitive java.corba; requires transitive java.transaction; requires transitive java.xml.bind; requires transitive java.xml.ws; requires transitive java.xml.ws.annotation; } 84/136

Slide 85

Slide 85 text

85/136

Slide 86

Slide 86 text

Кроме того, системные модули могут быть: • Aggregator (например, java.se) • Deprecated и Deprecated for removal (например, java.se.ee) • Upgradeable (например, jdk.internal.vm.compiler) 86/136

Slide 87

Slide 87 text

Кроме того, системные модули могут быть: • Aggregator (например, java.se) • Deprecated и Deprecated for removal (например, java.se.ee) • Upgradeable (например, jdk.internal.vm.compiler) • Incubating (например, jdk.incubator.httpclient) 87/136

Slide 88

Slide 88 text

Миграция 88/136

Slide 89

Slide 89 text

app1 app3 app2 foo-1.0.jar bar-0.0.1.jar baz-3.17.jar qux-2.1.jar java.prefs java.xml 89/136

Slide 90

Slide 90 text

app1 app3 app2 foo-1.0.jar bar-0.0.1.jar baz-3.17.jar qux-2.1.jar java.prefs java.xml 90/136

Slide 91

Slide 91 text

foo-1.0.jar bar-0.0.1.jar baz-3.17.jar qux-2.1.jar java.prefs java.xml app3 app2 app1 91/136

Slide 92

Slide 92 text

foo-1.0.jar bar-0.0.1.jar baz-3.17.jar qux-2.1.jar java.prefs java.xml requires app3 requires app2 app3 app2 app1 92/136

Slide 93

Slide 93 text

foo-1.0.jar bar-0.0.1.jar baz-3.17.jar qux-2.1.jar java.prefs java.xml requires app3 requires app2 requires ??? app3 app2 app1 requires ??? 93/136

Slide 94

Slide 94 text

foo-1.0.jar bar-0.0.1.jar baz-3.17.jar qux-2.1.jar java.prefs java.xml automatic modules automatic modules requires app3 requires app2 requires ??? app3 app2 app1 requires ??? 94/136

Slide 95

Slide 95 text

Automatic module • Имя выводится из имени jar-файла (или из атрибута Automatic-Module-Name) 95/136

Slide 96

Slide 96 text

foo-1.0.jar bar-0.0.1.jar baz-3.17.jar qux-2.1.jar java.prefs java.xml automatic modules automatic modules requires app3 requires app2 requires foo app3 app2 app1 requires bar 96/136

Slide 97

Slide 97 text

Automatic module • Имя выводится из имени jar-файла (или из атрибута Automatic-Module-Name) • Requires all modules • Exports all packages • Opens all packages 97/136

Slide 98

Slide 98 text

app1 app3 app2 foo-1.0.jar bar-0.0.1.jar baz-3.17.jar qux-2.1.jar java.prefs java.xml 98/136

Slide 99

Slide 99 text

foo-1.0.jar bar-0.0.1.jar baz-3.17.jar qux-2.1.jar java.prefs java.xml app1 app2 app3 99/136

Slide 100

Slide 100 text

app1 app3 app2 foo-1.0.jar bar-0.0.1.jar baz-3.17.jar qux-2.1.jar java.prefs java.xml 100/136

Slide 101

Slide 101 text

app1 app3 app2 foo-1.0.jar bar-0.0.1.jar baz-3.17.jar qux-2.2.jar java.prefs java.xml 101/136

Slide 102

Slide 102 text

app1 app3 app2 foo-1.0.jar bar-0.0.1.jar baz-3.18.jar qux-2.2.jar java.prefs java.xml 102/136

Slide 103

Slide 103 text

app1 app3 app2 foo-1.1.jar bar-0.0.1.jar baz-3.18.jar qux-2.2.jar java.prefs java.xml 103/136

Slide 104

Slide 104 text

app1 app3 app2 foo-1.0.jar bar-0.0.2.jar baz-3.17.jar qux-2.2.jar java.prefs java.xml 104/136

Slide 105

Slide 105 text

Сервисы 105/136

Slide 106

Slide 106 text

Сервисы • Появились в Java 6 106/136

Slide 107

Slide 107 text

Сервисы • Появились в Java 6 • В Java 9 стали намного удобнее и безопаснее 107/136

Slide 108

Slide 108 text

package com.foo; public interface Calculator { int square(int x); } module foo { exports com.foo; } 108/136

Slide 109

Slide 109 text

package com.foo; public interface Calculator { int square(int x); } module foo { exports com.foo; } public class Main { … } 109/136

Slide 110

Slide 110 text

package com.foo; public interface Calculator { int square(int x); } package com.bar; public class CalculatorImpl implements Calculator { @Override public int square(int x) { return x * x; } } module foo { exports com.foo; } module bar { requires foo; } public class Main { … } 110/136

Slide 111

Slide 111 text

package com.foo; public interface Calculator { int square(int x); } package com.bar; public class CalculatorImpl implements Calculator { @Override public int square(int x) { return x * x; } } module foo { exports com.foo; uses Calculator; } module bar { requires foo; provides Calculator with CalculatorImpl; } public class Main { … } 111/136

Slide 112

Slide 112 text

package com.foo; public interface Calculator { int square(int x); static Calculator get() {…} } package com.bar; public class CalculatorImpl implements Calculator { @Override public int square(int x) { return x * x; } } module foo { exports com.foo; uses Calculator; } module bar { requires foo; provides Calculator with CalculatorImpl; } public class Main { … } 112/136

Slide 113

Slide 113 text

package com.foo; import java.util.ServiceLoader; public interface Calculator { int square(int x); static Calculator get() { return ServiceLoader .load(Calculator.class) .findFirst() // Optional .orElseThrow(() -> new RuntimeException( "No Calculator provider found")); } } 113/136

Slide 114

Slide 114 text

package com.foo; import java.util.ServiceLoader; public interface Calculator { int square(int x); static List get() { return ServiceLoader .load(Calculator.class) .stream() .collect(Collectors.toUnmodifiableList()); } } 114/136

Slide 115

Slide 115 text

java.scripting ScriptEngineFactory jdk.scripting.nashorn NashornScriptEngineFactory 115/136

Slide 116

Slide 116 text

java.base ToolProvider jdk.compiler JavacToolProvider jdk.jlink JlinkToolProvider jdk.jartool JarToolProvider 116/136

Slide 117

Slide 117 text

Optional jar = ToolProvider.findFirst("jar"); 117/136

Slide 118

Slide 118 text

Optional jar = ToolProvider.findFirst("jar"); jar.get().run( System.out, System.err, "--describe-module", "--file", "path/to/some/module.jar"); 118/136

Slide 119

Slide 119 text

Демонстрация • Java 10 приложение с использованием сервисов • git clone https://github.com/orionll/services-demo 119/136

Slide 120

Slide 120 text

Демонстрация • Java 10 приложение с использованием сервисов • git clone https://github.com/orionll/services-demo 120/136

Slide 121

Slide 121 text

Демонстрация • Java 10 приложение с использованием сервисов • git clone https://github.com/orionll/services-demo FigureDescriptorProvider BaseFigureDescriptorProvider ExtFigureDescriptorProvider 121/136

Slide 122

Slide 122 text

Резюме 122/136

Slide 123

Slide 123 text

Резюме • Система модулей улучшает архитектуру проекта 123/136

Slide 124

Slide 124 text

Резюме • Система модулей улучшает архитектуру проекта • Делает приложение более безопасным 124/136

Slide 125

Slide 125 text

Резюме • Система модулей улучшает архитектуру проекта • Делает приложение более безопасным • Предоставляет механизмы для облегчения разработки крупных систем (сервисы, upgradeable modules) 125/136

Slide 126

Slide 126 text

Резюме • Система модулей улучшает архитектуру проекта • Делает приложение более безопасным • Предоставляет механизмы для облегчения разработки крупных систем (сервисы, upgradeable modules) • Улучшает производительность 126/136

Slide 127

Slide 127 text

Недостатки 127/136

Slide 128

Slide 128 text

Недостатки Сложность: • -classpath vs --module-path vs --upgrade-module-path • non-modular jar vs modular jar vs automatic jar • Много новых опций (--add-modules, --add-exports, --patch-module…) • Много новых инструментов (jlink, jimage, jmod, jdeps) 128/136

Slide 129

Slide 129 text

Недостатки Сложность: • -classpath vs --module-path vs --upgrade-module-path • non-modular jar vs modular jar vs automatic jar • Много новых опций (--add-modules, --add-exports, --patch-module…) • Много новых инструментов (jlink, jimage, jmod, jdeps) Закрытые split-пакеты запрещены. 129/136

Slide 130

Slide 130 text

Нужно ли прямо сейчас переходить на модули? 130/136

Slide 131

Slide 131 text

Экосистема ещё довольно плохо готова к модульности • Инструменты плохо готовы (IDE, системы сборки, контейнеры, тест-фреймворки) 131/136

Slide 132

Slide 132 text

Экосистема ещё довольно плохо готова к модульности • Инструменты плохо готовы (IDE, системы сборки, контейнеры, тест-фреймворки) • Automatic-Module-Name почти нигде нет 132/136

Slide 133

Slide 133 text

Экосистема ещё довольно плохо готова к модульности • Инструменты плохо готовы (IDE, системы сборки, контейнеры, тест-фреймворки) • Automatic-Module-Name почти нигде нет • Split packages кругом (например, jsr305 и java.xml.ws.annotation) 133/136

Slide 134

Slide 134 text

Экосистема ещё довольно плохо готова к модульности • Инструменты плохо готовы (IDE, системы сборки, контейнеры, тест-фреймворки) • Automatic-Module-Name почти нигде нет • Split packages кругом (например, jsr305 и java.xml.ws.annotation) • Многие библиотеки используют private API 134/136

Slide 135

Slide 135 text

Полезные ссылки • Project Jigsaw: http://openjdk.java.net/projects/jigsaw/ • Replacements for deprecated java.se.ee modules: https://stackoverflow.com/questions/48204141/replacements -for-deprecated-jpms-modules-with-java-ee-apis • jdeps: https://docs.oracle.com/javase/10/tools/jdeps.htm • jlink: https://docs.oracle.com/javase/10/tools/jlink.htm • Services Demo: https://github.com/orionll/services-demo 135/136

Slide 136

Slide 136 text

Спасибо за внимание! Java 10 136/136