1. Java 9 - не только модули
Иван Крылов
1
@JohnWings
ivankrylov.java@gmail.com
2. О чем будем говорить
• Два слайда про нас (Azul Systems)
• Изменения в языке
• Новые фабричные методы для
коллекций
• Новое в Stream API
• Spin Loop Hints
• Process API
• HTTP/2
• JVM changes
• Stack Walking API
• Обзор прочих JEPов
• JShell
2
Ivan Krylov
3. Zing: Виртуальная Java-машина для крупного бизнеса
• Главная цель - улучшение показателей функционирования виртуальной
Java-машины для предприятий
• Новый JIT компилятор на базе LLVM
• Сборка мусора больше не влияет на производительность приложений
• Решенная проблема "прогрева" ВМки
• Неизменная производительность - не просто быстро, а ВСЕГДА быстро
• Широчайшая сфера применения:
• от интерактивных приложений до задач, критичных ко времени отклика
• от микросервисов до приложений, требующих больших объемов памяти
• Устраняет необходимость в большинстве известных "костылей" в вашем
коде
3
4. Zulu (Embedded): Когда нужны решения для встроенных систем
• 100% открытый код - технология, основанная на OpenJDK
• Сертифицирована на совместимость и соответствие Java SE
• Показатели функционирования, идентичные OpenJDK и
Oracle Java SE
• Высококлассная поддержка
• Релизация для Linux x86, ARM32, ARM64, PPC32, MIPS, а
также Windows и Mac OS
4
8. 9
interface I {
private I foo() { return null; } // OK.
void foo(int x); // OK.
private void foo(String s);
// Error: private method must declare body.
private abstract void foo(int i, int j);
// Error: private & abstract: bad combo.
}
Приватные методы в интерфейсах
9. Приватные методы в интерфейсах
13
public interface II {
private void log(int x, int y, int z) {
System.out.println("x="+x+" y="+y+" z="+z);
}
default int sum(int x, int y) {
log(x,y,x+y);
return x+y;
}
default int mul(int x, int y) {
log(x,y,x*y);
return x*y;
}
}
10. Effectively-final переменные
в try-with-resources выражениях
14
public static void main(String... args) {
FileReader f = new FileReader("test.txt");
BufferedReader br = new BufferedReader(fr);
try (br) {
// do something
} catch (Exception ex) {
}
}
public static void main(String... args) {
FileReader f = new FileReader(“test.txt");
try (br = new BufferedReader(fr)) {
// do something
} catch (Exception ex) {
}
}
12. В Java 8
./TypeInferrenceTest.java:7: error: cannot infer
type arguments for HashMap<K,V>
new HashMap<>()
^
reason: cannot use '<>' with anonymous inner classes
where K,V are type-variables:
K extends Object declared in class HashMap
V extends Object declared in class HashMap
1 error
Diamond с анонимными классами
16
class TypeInferrenceTest {
Map<String, String> map =
new HashMap<> ()
{
{
map.put("key", "value");
}
};
}
13. Запрет на использование _ в именах
17
// -source 8:
// warning: as of release 9, '_' is a keyword,
// and may not be used as an identifier
// -source 9:
// error: as of release 9, '_' is a keyword,
// and may not be used as an identifier
class UnderscoreAsIdentifierWarning {
String _ = null;
}
14. Другие обновления языка (?)
Надоело писать имя типа в декларации переменной?
18
var list = new ArrayList<String>();
JEP-286 Local-Variable Type Inference. Пока что только “кандидат”
var result = processNewCustomerAdded();
15. Фабричные методы для коллекций
Создание неизменных контейнеров
19
Set<String> set = new HashSet<>();
set.add("a");
set.add("b");
set = Collections.unmodifiableSet(set);
Set<String> set = Collections.unmodifiableSet(
new HashSet<>(Arrays.asList("a", "b")));
Set<String> set = Collections.unmodifiableSet(
new HashSet<String>() {{
add("a");
add("b");
}});
Set<String> set = Collections.unmodifiableSet(
Stream.of("a", “b").collect(toSet())
);
Set<String> set = Set.of("a", "b");
17. Новое в Stream API (1)
22
Stream::takeWhile
while (predicate_on_stream_element) {
<keep processing this ordered stream>
};
Stream.of(3, 2, 1, 0, -1, 0, 1, 2, 3)
.takeWhile(s -> s > 0)
.forEach(System.out::println);
3
2
1
18. Новое в Stream API (2)
23
Stream::dropWhile
while (predicate_on_stream_element) {
<skip element of this ordered stream>
};
Stream.of(3, 2, 1, 0, -1, 0, 1, 2, 3)
.dropWhile(s -> s > 0)
.forEach(System.out::println);
0
-1
0
1
2
3
19. Новое в Stream API (3)
24
• Stream::Iterate с предикатом
Stream.iterate(3, i -> i > 0, i -> i-1)
.forEach(System.out::println);
3
2
1
версия для Java 8:
Stream.iterate(3, i -> i-1)
.limit(3)
.forEach(System.out::println);
20. Stream API changes (4)
25
Stream::ofNullable
Фактори для одного ненулевого элемента
long a = Stream.ofNullable(1).count();
long b = Stream.ofNullable(null).count();
System.out.println(a);
System.out.println(b);
1
0
21. Spin Loop Hint (JEP-285)
• Цель: latency (и производительность)
• Весь API:
• Метод j.l.Thread.onSpinWait()
• На x86 используется инструкция ‘pause’
• Используется в JSR 166 для JDK9
• java/util/concurrent/locks/StampedLock.java
• java/util/concurrent/Phaser.java
• java/util/concurrent/SynchronousQueue.java
class EventHandler {
volatile boolean eventNotificationNotReceived;
void waitForEventAndHandleIt() {
while ( eventNotificationNotReceived ) {
java.lang.Thread.onSpinWait();
}
readAndProcessEvent();
}
void readAndProcessEvent() {
// Read event from some source and process it
. . .
}
}
26
24. Spin Loop Hint - source level
совместимость
• Допустим, есть код, собирающийся 8-кой
• Используйте Agrona library
• или подсмотрите в java/org/agrona/hints/ThreadHints.java
• Поддержка, начиная с Java 7
29
https://github.com/real-logic/Agrona/blob/master/src/main/java/org/agrona/hints/ThreadHints.java
25. Код для разных версий Java
• Писать все только под самый старый javaс
• Разные артифакты
• “Толстые” jar архивы (начиная с 9)
26. Multi-Release JARs (JEP-238)
31
…
Код для JRE версии меньше 9
Код для JRE версии 9
Код для JRE версии 10
MANIFEST.MF: Multi-Release: true
<root>/META-INF/versions/ ..
27. • https://github.com/ivankrylov/onSpinWaitMultiReleaseJar
• onSpinWait Wrapper
• javac + make
• http://in.relation.to/2017/02/13/building-multi-release-jars-with-maven/
• Get pid of jvm
• Maven Antrun + resources + maven-jar-plugin
• http://word-bits.flurg.com/multrelease-jars/
Примеры Multi-Release JARs
32
28. Garbage First включен по умолчанию
• Самый современный GC в Hotspot
• Региональный параллельный одновременный коллектор
• Предсказуемые паузы и высокая производительность!
• По умолчанию => Ошибки в GC находятся быстрее
33
29. Garbage First включен по умолчанию
• Эргономика работает по-другому. Могут
проявиться ошибки в синхронизации
• Были (есть(?)) несовместимости с G1 в Cassandra,
Elasticsearch, Lucene, и т.п,.
• (июль 2015): https://groups.google.com/forum/#!topic/
mechanical-sympathy/JxsuVtIIOaY
34
30. Пережить смену default GC, не теряя сон
• Если до сих пор вас устраивали настройки GC по
умолчанию
• запаситесь данными эргономики для вашего приложения и
среды внедрения (-XX:+PrintFlagsFinal)
• пропишите их в деплоймент скриптах
• Если вы и ранее явно выбирали GC и флаги GC
• Ничего не изменится, старые коллекторы не исчезнут
• Тестируйте с G1. Не дожидаясь Java 9.
35
31. Хороший повод узнать побольше про GC
• Экспериментируйте с G1
• Главное - понимать основные принципы работы GC
• Прежде всего - метрики, которыми оценивают алгоритмы GC
• Что еще почитать: http://www.infoq.com/minibooks/java-garbage-
collection
36
32. Другие изменения в GC
• Deprecate CMS
• Deprecate - значит запретить, но в будущем (после 9ки)
• Shenandoah GC (JEP-189)
• Первый OpenJDK GC не от Оракла
• Создание GC интерфейса
• https://bugs.openjdk.java.net/browse/JDK-8163329
37
33. Обновление Process API
• JEP 102: Process API Updates
• Новое:
• Получить pid “своей” JVM
• Получить список процессов
системы
• Работа с деревьями процессов
• supportsNormalTermination() ?
Source: http://blog.takipi.com/java-9-the-ultimate-feature-list/ 38
34. Пример Process API
Source: http://blog.takipi.com/java-9-the-ultimate-feature-list/ 39
Process proc = Runtime.getRuntime()
.exec(new String[]{"/bin/sh",
"-c", "echo $PPID"});
if (proc.waitFor()==0) {
InputStream in = proc.getInputStream();
int available = in.available();
byte[] outputBytes = new byte[available];
in.read(outputBytes);
String pid = new String(outputBytes);
System.out.println("Your pid is " + pid)
}
System.out.println("Your pid is "
+ ProcessHandle.current().getPid());
46. Обзор JEP-ов. Что уберут?
• 231: Remove Launch-Time JRE
Version Selection
• 240: Remove the JVM TI hprof
Agent
• 241: Remove the jhat Tool
65
• Последствия
модулярности (JEP - 261)
• -Xbootclasspath
• -Xbootclasspath/p
• system property
sun.boot.class.path
47. JShell
• Развива(ется/лся) в рамках
проекта Kulla
• Позволяет попробовать
синтаксис без написания
законченной программы
• Помогает обучать языку Java
class HelloWorld {
public static void main(String[] args) {
System.out.println("Hello World!");
}
}
66