Поддержка Java 8
на уровне JVM
Никита Липский
Excelsior LLC
1
2
3
4
Кто знает про себя ?
• Более 20 лет профессиональной карьеры
• Инициатор проекта Excelsior JET
– работал над проектом более 17 лет
– как идейный вдохновитель
– компиляторный инженер
– руководитель
– и много в каких еще ролях
• Open source проекты WebFX и Java ReStart
– в свободное от работы время
• twitter: @pjBooms
5
Кто знает про Excelsior JET?
• Полная реализация Java SE
– c 2005 года cертифицирована как Java Compatible
• AOT compiler + Java Runtime
– смешанная компиляция: AOT + JIT
– поддержка нестандартных загрузчиков классов в AOT режиме (для
Eclipse RCP, Tomcat)
• Toolkit
– Startup Optimizer
– Deployment
6
Кто знает про Excelsior JET?
Кто знает про Excelsior JET?Кто знает про Excelsior JET?
7
Что добавлено в Java 8
• Lambda-expressions
• Default Methods
• Stream API, Time API
• Type annotations, Parameter names
• JavaFX 8
• Nashorn
• Compact Profiles
8
Default methods
9
Default Methods
• Методы с телами в интерфейсах
– Мотивация: расширение Java API, не ломая
обратную совместимость
List<Person> list = ...
list.forEach(System.out::println)
forEach нет в Java 7
10
Default Methods
Повлияли на спецификацию JVM:
• Изменилась семантика invoke инструкций
байткода:
– invokespecial, invokevirtual, invokeinterface, invokestatic
• Изменилась процедура статической
инициализации класса
11
Resolve метода
• Все invoke инструкции (кроме
invokedynamic) ссылаются на вызываемый
метод cимвольно
• Перед тем как invoke инструкция
исполнится, должна пройти процедура
разрешения символьной ссылки на метод
12
Resolve метода
Пусть есть ссылка C.foo():
• Ищем foo в C:
• Если не нашли, ищем foo в суперклассах C
• Если не нашли, ищем foo в суперинтерфейсах C
• New in Java 8:
– при поиске метода в суперинтерфейсах, в начале
ищется максимально специфичный default метод
13
Resolve метода
Максимально специфичный default метод:
• default метод, который не переопределяется в
потомках данного интерфейса, которые
имплементируется классом C
• Если есть, то должен быть один
– Иначе процедура резолва бросает
IncompatibleClassChangeError
14
Resolve метода
interface I {
default void foo(){…}
}
class A {
void foo(){…}
}
class C extends A
implements I{
}
C.foo() - ?
15
Resolve метода
interface I {
default void foo(){…}
}
interface J extends I {
default void foo(){…}
}
class C implements J,I {
}
C.foo() - ?
16
Resolve метода
interface I {
default void foo(){…}
}
interface J {
default void foo(){…}
}
class C implements J,I {
}
C.foo() - ?
17
invokespecial
• Используется для вызова конструкторов и суперметодов
• При трансляции invokespecial в машинный код, целевой
метод всегда известен и
– может инлайниться сразу в вызывающий метод или
– может вызываться напрямую: call <MethodAddress>
• Вызывается метод (чаще всего), который возвращается
процедурой resolve метода
– т.o. может вызывать default методы в Java 8
18
invokevirtual
• Вызываемый метод зависит от объекта
получателя (this)
• Транслируется в машинный код как косвенный
вызов через таблицу виртуальных методов
invokevirtual <MethofRef>
->
call [<VMTAddress> +MethodSlotInVMT*C]
19
invokevirtual
• Схема представления объекта в памяти
20
21
abstract class A
implements I {
{
void meth1(){…}
abstract void meth2();
}
interface I {
void meth3();
}
class C extends A {
void meth2(){…}
void meth3(){…}
void meth4(){…}
}
AbstractMethodError
22
abstract class A
implements I {
{
void meth1(){…}
abstract void meth2();
}
interface I {
void meth3();
}
class C extends A {
implements J {
void meth2(){…}
}
interface J {
default void meth3(){…}
default void meth4(){…}
}
AbstractMethodError
New in Java 8
Поддержка default методов в
Excelsior JET
• Компиляция методов интерфейсов
• Изменение процедуры резолва методов
• Изменение процедуры заполнения VMT
23
Найденные баги при поддержки
Java 8 в Excelsior JET
• В JVM спецификации
– override метода
(https://bugs.openjdk.java.net/browse/JDK-8098577)
• В HotSpot
– статическая инициализация классов в присутствии default
методов инициализирует больше классов чем нужно
(https://bugs.openjdk.java.net/browse/JDK-8098557 )
– в resolve методов: “InterfaceMethod CP entry pointing to a
class should cause ICCE”
(https://bugs.openjdk.java.net/browse/JDK-8087223 )
24
Lambda выражения
25
Лямбда выражения
Было
new Thread(new Runnable() {
public void run() {
System.out.println(“Hi,I’m Thread”);
}
}).start();
26
Лямбда выражения
Стало …
new Thread(new Runnable() {
public void run() {
System.out.println(“Hi,I’m Thread”);
}
}).start();
27
Лямбда выражения
Стало
new Thread(()->
System.out.println(“Hi,I’m Thread”)
).start();
28
Лямбда выражения
Как лямбда-выражения повлияли
на спецификацию JVM?
29
Лямбда выражения
Как лямбда-выражения повлияли
на спецификацию JVM?
Никак!
30
Трансляция лямбда выражений в
Java байткод
class B {
public void foo() {
List<Person> list = ...
final int bottom = ..., top = ...;
list.removeIf( p ->
(p.size >= bottom && p.size <= top)
);
}
}
31
Трансляция лямбда выражений в
Java байткод
class B {
public void foo() {
List<Person> list = ...
final int bottom = ..., top = ...;
list.removeIf(new Predicate() {
public boolean apply(Person p) {
(p.size >= bottom && p.size <= top);
}
);
}
}
32
Трансляция лямбда выражений в
Java байткод
class B {
public void foo() {
List<Person> list = ...
final int bottom = ..., top = ...;
list.removeIf(new Predicate() {
public boolean apply(Object o) {
(p.size >= bottom && p.size <= top);
}
);
}
}
33
Трансляция лямбда выражений в
Java байткод
class B {
public void foo() {
List<Person> list = ...
final int bottom = ..., top = ...;
list.removeIf(
[lambda for lambda$1 as Predicate
capturing (bottom, top) ]
}
static boolean lambda$1(int bottom, int top, Person p)
{
return p.size >= bottom && p.size <= top;
}
}
34
Трансляция лямбда выражений в
Java байткод
class B {
public void foo() {
List<Person> list = ...
final int bottom = ..., top = ...;
list.removeIf(
indy((MH(metaFactory), //bootstrap
MH(invokeVirtual Predicate.apply),
MH(invokeStatic B.lambda$1))(bottom, top))
}
static boolean lambda$1(int bottom, int top, Person p)
{
return p.size >= bottom && p.size <= top;
}
}
35
Indy
Indy – сокращение от invokedynamic
• В первый раз indy зовет bootstrap метод,
который возвращает объект CallSite
• Далее и при последующих вызовах от объекта
callsite берется МethodHandle и зовется
invokeExact
36
MethodHandle
MethodHandle – целевой объект indy:
• может возвращать всегда одно и то же
• может быть доступом к полю, методу
• адаптером других MethodHandle
– адаптеры аргументов
– частичное применение аргументов (binding)
– условный переход (guardWithTest)
37
LambdaMetaFactory
j.l.invoke.LambdaMetaFactory.metafaсtory:
• bootstrap метод для invokedynamic,
порождающих лямбды
• Порождает RT-анонимный класс для лямбды,
реализующий SAM тип
• Создает и возвращает ConstantCallSite, чей
MethodHandle бывает двух типов:
38
LambdaMetaFactory
MethodHandle возвращаемый LambdaMetaFactory:
• Если у лямбды нет контекста, то возвращается
константный MethodHandle от лямбда-объекта
(кэширование лямбды)
• Если у лямбды есть контекст, то возвращается
ссылка на статическую фабрику класса лямбды
39
Runtime анонимные классы
• Настолько анонимные, что их даже нет в
JVM спецификации
– полную семантику возможно вычислить только
из исходных текстов HotSpot
40
Runtime анонимные классы
• Из Java создаются через
Unsafe.defineAnonymousClass
• Не принадлежат никакому класслоадеру, их
нельзя найти, умирают раньше других классов
• В Java 8 их семантика поменялась
– они могут доступаться до private членов классов их
породивших (до тел лямбд)
41
Оптимизации лямбд
Задача: Пусть есть Java код
Runnable r =
()->System.out.println(“Hi”);
r.run();
Требуется: вместо этого кода породить:
System.out.println(“Hi”);
42
Решение HotSpot
• Интерпретируем код метода, пока он не станет
горячим
– порождая и загружая анонимный класс для
лямбда выражения
• Инлайним в код целевого метода сначала код
единственного метода анонимного класса, а
затем и само тело лямбды
• Анонимный класс собираем GC
43
Решение JET*
• Восстанавливаем из байткода в статическом
компиляторе лямбда-выражение в исходном
виде
• Вычисляем, что единственное использование
лямбды – это ее непосредственный вызов
• Инлайним тело лямбда выражения
* Пока не реализовано
44
Решение JET*
А если нам не удалось заинлайнить метод
куда передается лямбда-выражение?
45
Решение JET*
46
(p -> (p.size >= bottom && p.size <= top))
lambda$1: код тела лямбды
захваченный контекст
Решение JET*
47
(p -> (p.size >= bottom && p.size <= top))
j.l.Object methods
при вызове getClass() ,
создается класс на лету
lambda$1: код тела лямбды
захваченный контекст
Не нужно создавать класс для
большинства случаев
Лямбды в JET: текущий статус
• Пока создаются через indy, но тела лямбд
статически компилируются
• Классы лямбд динамически компилируются
– очень быстро <1ms
• В разработке: AOT порождение классов лямбд
и их AOT компиляция
• В планах: удаление избыточности
– класс для лямбды не всегда нужен
48
Типовые аннотации
49
Типовые аннотации
Могут быть везде где есть тип:
class TypeAnnotationsExample {
@Encrypted String data;
List<@NonNull String> strings;
HashSet names =
(@Immutable HashSet) set;
}
50
Типовые аннотации
• Доступны в рантайм через Reflection API:
– getTypeAnnotations
• Кодируются в Java байткоде атрибутом
типа Runtime(In)VisibleTypeAnnotation –
новые атрибуты Java 8 байткода
51
Имена параметров
• Если javac задать ключ –parameters,
то
– в класс-файл будут писаться имена параметров
– имена параметров будут доступны через
reflection
• Используются в Spring MVC
52
New Java 8 APIs
53
New Java 8 APIs
• Stream API
• Time API
• JavaFX 8
• Nashorn
Также как и все о
54
New Java 8 APIs
• Stream API
• Time API
• JavaFX 8
• Nashorn
Как поддерживаются в JET?
55
New Java 8 APIs
• Excelsior – официальный Java SE licensee
– лицензируем все исходные тексты Java SE у Oracle
– можем поступать с ними как хотим, например
компилировать Java байт-код платформы в
машинный код и использовать свою реализацию
JVM
– обязаны проходить тесты на совместимость (JCK)
56
New Java 8 APIs
Не все Java 8 APIs одинаково стандартны:
• Stream API, Time API входят в стандарт
Java 8
• Nashorn, JavaFX НЕ входят в стандарт Java SE
– в частности нет тестов JCK
57
Структура Oracle JRE
58
Структура Oracle JRE
• Классы Nashorn и JavaFX находятся в папке
ext
– грузятся Extension класслоадером
• Все что находится в папке ext можно
официально не включать в Private JRE
дистрибутива своего приложения
59
Распространение приложений
скомпилированных Excelsior JET
• Скомпилированные с помощью Excelsior JET
приложения всегда распространяются с
приватной копией JET Runtime:
– ваши пользователи не должны ставить “Excelsior
JRE”
– New in Java 8: автоматически НЕ включает JavaFX и
Nashorn, если они не используются вашим
приложением
60
Compact Profiles
61
Compact Profiles
Compact1 Compact2 Compact3
java.lang java.rmi java.lang.instrument
java.io java.sql java.lang.management
java.math javax.transaction javax.management
java.nio javax.xml javax.naming
java.util org.w3c.dom javax.script
java.net org.xml.sax javax.security
java.security javax.sql
javax.crypto javax.xml.crypto
java.text org.ietf.jgss
62
Compact Profiles
• Есть в Java SE Embedded (Linux builds)
• В OpenJDK (не собираются на Windows и
Mac OS X)
63
История компонентизации
Java SE от Excelsior
• Разбиение Java SE на APIs (2000 год)
– компиляция их в DLL
• JetPerfect (2001 год)
– компиляция приложений с нужными частями Java SE в один
EXE файл
– SWT Example: 1.4 MB
• Java Runtime Slim-Down (2007 год)
– совместимое с Java SE спецификацией решение
• Compact Profiles (2016 год)
64
История компонентизации
Java SE от Sun/Oracle
• Kernel JRE (2006 год)
• Project Jigsaw 2007 – 2017(?)
• Compact Profiles (2014 год)
65
Compact Profiles
• Первый рабочий и легальный способ
уменьшения Private JRE
• Есть JCK (тесты совместимости)
66
Compact Profiles
• Первый рабочий и легальный способ
уменьшения Private JRE
• Есть JCK (тесты совместимости)
• Есть в Excelsior JET для всех десктопных
платформ (Windows, Linux, Mac OS X) и в
embedded (Linux ARM)
67
JavaFX on Compact Profiles
68
JavaFX 8 on Compact Profiles
• JavaFX условно состоит из трех логических
частей:
– Core JavaFX
– JavaFX Web (WebKit based)
– JavaFX bridges to Swing и SWT
69
JavaFX 8 on Compact Profiles
• Core JavaFX может работать на Compact2
– FXML зависит от XML
• JavaFX Swing Bridge требует Full Java SE
– Так как очевидно зависит от Swing
70
JavaFX 8 on Compact Profiles
• JavaFX Web тоже имеет зависимости от AWT
…
71
JavaFX 8 on Compact Profiles
• JavaFX Web тоже имеет зависимости от
AWT, которые не разрешаются во время
исполнения !
72
JavaFX 8 on Compact Profiles
• JavaFX Web тоже имеет зависимости от
AWT, которые не разрешаются во время
исполнения, кроме одной  …
73
JavaFX 8 on Compact Profiles
• JavaFX Web тоже имеет зависимости от
AWT, которые не разрешаются во время
исполнения, кроме одной, которая тоже не
разрешается в режиме -Xverify:none
74
JavaFX 8 on Compact Profiles
Поддержка JavaFX Web в Excelsior JET:
• зависимости от AWT откладываются до разрешения
во время исполнения
– не разрешаются в статическом компиляторе
• Все классы JavaFX верифицируются до исполнения
– не требуется верификация во время исполнения и
загрузка “лишних” классов
• В результате JavaFX Web работает на Compact2!
75
Java Packager (Oracle JDK) vs.
JetPackII (Excelsior JET)
Java
Packager
JetPackII with Compact
Profiles
Ensemble Demo
(with WebView sample)
46 MB 21 MB
BrickBreaker 42 MB 10 MB
76
Примечание: замеры производились на Windows 32-bit для Java 8 Update 72,
представлены размеры дистрибутивов без зависимостей
Заключение
• Java 8 – лучший релиз Java со времен Java 5
– лямбды повышают производительность труда
• Лямбды не повлияли на спецификацию JVM
– но желательна специальная поддержка в JVM
• Compact Profiles уменьшают размер Private JRE
– важно для магазинов приложений и в embedded
• Java != HotSpot
77
Вопросы и ответы
Никита Липский,
Excelsior
nlipsky@excelsior-usa.com
twitter: @pjBooms 78

Java 8 Support at the JVM Level

  • 1.
    Поддержка Java 8 науровне JVM Никита Липский Excelsior LLC 1
  • 2.
  • 3.
  • 4.
  • 5.
    Кто знает просебя ? • Более 20 лет профессиональной карьеры • Инициатор проекта Excelsior JET – работал над проектом более 17 лет – как идейный вдохновитель – компиляторный инженер – руководитель – и много в каких еще ролях • Open source проекты WebFX и Java ReStart – в свободное от работы время • twitter: @pjBooms 5
  • 6.
    Кто знает проExcelsior JET? • Полная реализация Java SE – c 2005 года cертифицирована как Java Compatible • AOT compiler + Java Runtime – смешанная компиляция: AOT + JIT – поддержка нестандартных загрузчиков классов в AOT режиме (для Eclipse RCP, Tomcat) • Toolkit – Startup Optimizer – Deployment 6
  • 7.
    Кто знает проExcelsior JET? Кто знает про Excelsior JET?Кто знает про Excelsior JET? 7
  • 8.
    Что добавлено вJava 8 • Lambda-expressions • Default Methods • Stream API, Time API • Type annotations, Parameter names • JavaFX 8 • Nashorn • Compact Profiles 8
  • 9.
  • 10.
    Default Methods • Методыс телами в интерфейсах – Мотивация: расширение Java API, не ломая обратную совместимость List<Person> list = ... list.forEach(System.out::println) forEach нет в Java 7 10
  • 11.
    Default Methods Повлияли наспецификацию JVM: • Изменилась семантика invoke инструкций байткода: – invokespecial, invokevirtual, invokeinterface, invokestatic • Изменилась процедура статической инициализации класса 11
  • 12.
    Resolve метода • Всеinvoke инструкции (кроме invokedynamic) ссылаются на вызываемый метод cимвольно • Перед тем как invoke инструкция исполнится, должна пройти процедура разрешения символьной ссылки на метод 12
  • 13.
    Resolve метода Пусть естьссылка C.foo(): • Ищем foo в C: • Если не нашли, ищем foo в суперклассах C • Если не нашли, ищем foo в суперинтерфейсах C • New in Java 8: – при поиске метода в суперинтерфейсах, в начале ищется максимально специфичный default метод 13
  • 14.
    Resolve метода Максимально специфичныйdefault метод: • default метод, который не переопределяется в потомках данного интерфейса, которые имплементируется классом C • Если есть, то должен быть один – Иначе процедура резолва бросает IncompatibleClassChangeError 14
  • 15.
    Resolve метода interface I{ default void foo(){…} } class A { void foo(){…} } class C extends A implements I{ } C.foo() - ? 15
  • 16.
    Resolve метода interface I{ default void foo(){…} } interface J extends I { default void foo(){…} } class C implements J,I { } C.foo() - ? 16
  • 17.
    Resolve метода interface I{ default void foo(){…} } interface J { default void foo(){…} } class C implements J,I { } C.foo() - ? 17
  • 18.
    invokespecial • Используется длявызова конструкторов и суперметодов • При трансляции invokespecial в машинный код, целевой метод всегда известен и – может инлайниться сразу в вызывающий метод или – может вызываться напрямую: call <MethodAddress> • Вызывается метод (чаще всего), который возвращается процедурой resolve метода – т.o. может вызывать default методы в Java 8 18
  • 19.
    invokevirtual • Вызываемый методзависит от объекта получателя (this) • Транслируется в машинный код как косвенный вызов через таблицу виртуальных методов invokevirtual <MethofRef> -> call [<VMTAddress> +MethodSlotInVMT*C] 19
  • 20.
  • 21.
    21 abstract class A implementsI { { void meth1(){…} abstract void meth2(); } interface I { void meth3(); } class C extends A { void meth2(){…} void meth3(){…} void meth4(){…} } AbstractMethodError
  • 22.
    22 abstract class A implementsI { { void meth1(){…} abstract void meth2(); } interface I { void meth3(); } class C extends A { implements J { void meth2(){…} } interface J { default void meth3(){…} default void meth4(){…} } AbstractMethodError New in Java 8
  • 23.
    Поддержка default методовв Excelsior JET • Компиляция методов интерфейсов • Изменение процедуры резолва методов • Изменение процедуры заполнения VMT 23
  • 24.
    Найденные баги приподдержки Java 8 в Excelsior JET • В JVM спецификации – override метода (https://bugs.openjdk.java.net/browse/JDK-8098577) • В HotSpot – статическая инициализация классов в присутствии default методов инициализирует больше классов чем нужно (https://bugs.openjdk.java.net/browse/JDK-8098557 ) – в resolve методов: “InterfaceMethod CP entry pointing to a class should cause ICCE” (https://bugs.openjdk.java.net/browse/JDK-8087223 ) 24
  • 25.
  • 26.
    Лямбда выражения Было new Thread(newRunnable() { public void run() { System.out.println(“Hi,I’m Thread”); } }).start(); 26
  • 27.
    Лямбда выражения Стало … newThread(new Runnable() { public void run() { System.out.println(“Hi,I’m Thread”); } }).start(); 27
  • 28.
  • 29.
    Лямбда выражения Как лямбда-выраженияповлияли на спецификацию JVM? 29
  • 30.
    Лямбда выражения Как лямбда-выраженияповлияли на спецификацию JVM? Никак! 30
  • 31.
    Трансляция лямбда выраженийв Java байткод class B { public void foo() { List<Person> list = ... final int bottom = ..., top = ...; list.removeIf( p -> (p.size >= bottom && p.size <= top) ); } } 31
  • 32.
    Трансляция лямбда выраженийв Java байткод class B { public void foo() { List<Person> list = ... final int bottom = ..., top = ...; list.removeIf(new Predicate() { public boolean apply(Person p) { (p.size >= bottom && p.size <= top); } ); } } 32
  • 33.
    Трансляция лямбда выраженийв Java байткод class B { public void foo() { List<Person> list = ... final int bottom = ..., top = ...; list.removeIf(new Predicate() { public boolean apply(Object o) { (p.size >= bottom && p.size <= top); } ); } } 33
  • 34.
    Трансляция лямбда выраженийв Java байткод class B { public void foo() { List<Person> list = ... final int bottom = ..., top = ...; list.removeIf( [lambda for lambda$1 as Predicate capturing (bottom, top) ] } static boolean lambda$1(int bottom, int top, Person p) { return p.size >= bottom && p.size <= top; } } 34
  • 35.
    Трансляция лямбда выраженийв Java байткод class B { public void foo() { List<Person> list = ... final int bottom = ..., top = ...; list.removeIf( indy((MH(metaFactory), //bootstrap MH(invokeVirtual Predicate.apply), MH(invokeStatic B.lambda$1))(bottom, top)) } static boolean lambda$1(int bottom, int top, Person p) { return p.size >= bottom && p.size <= top; } } 35
  • 36.
    Indy Indy – сокращениеот invokedynamic • В первый раз indy зовет bootstrap метод, который возвращает объект CallSite • Далее и при последующих вызовах от объекта callsite берется МethodHandle и зовется invokeExact 36
  • 37.
    MethodHandle MethodHandle – целевойобъект indy: • может возвращать всегда одно и то же • может быть доступом к полю, методу • адаптером других MethodHandle – адаптеры аргументов – частичное применение аргументов (binding) – условный переход (guardWithTest) 37
  • 38.
    LambdaMetaFactory j.l.invoke.LambdaMetaFactory.metafaсtory: • bootstrap методдля invokedynamic, порождающих лямбды • Порождает RT-анонимный класс для лямбды, реализующий SAM тип • Создает и возвращает ConstantCallSite, чей MethodHandle бывает двух типов: 38
  • 39.
    LambdaMetaFactory MethodHandle возвращаемый LambdaMetaFactory: •Если у лямбды нет контекста, то возвращается константный MethodHandle от лямбда-объекта (кэширование лямбды) • Если у лямбды есть контекст, то возвращается ссылка на статическую фабрику класса лямбды 39
  • 40.
    Runtime анонимные классы •Настолько анонимные, что их даже нет в JVM спецификации – полную семантику возможно вычислить только из исходных текстов HotSpot 40
  • 41.
    Runtime анонимные классы •Из Java создаются через Unsafe.defineAnonymousClass • Не принадлежат никакому класслоадеру, их нельзя найти, умирают раньше других классов • В Java 8 их семантика поменялась – они могут доступаться до private членов классов их породивших (до тел лямбд) 41
  • 42.
    Оптимизации лямбд Задача: Пустьесть Java код Runnable r = ()->System.out.println(“Hi”); r.run(); Требуется: вместо этого кода породить: System.out.println(“Hi”); 42
  • 43.
    Решение HotSpot • Интерпретируемкод метода, пока он не станет горячим – порождая и загружая анонимный класс для лямбда выражения • Инлайним в код целевого метода сначала код единственного метода анонимного класса, а затем и само тело лямбды • Анонимный класс собираем GC 43
  • 44.
    Решение JET* • Восстанавливаемиз байткода в статическом компиляторе лямбда-выражение в исходном виде • Вычисляем, что единственное использование лямбды – это ее непосредственный вызов • Инлайним тело лямбда выражения * Пока не реализовано 44
  • 45.
    Решение JET* А еслинам не удалось заинлайнить метод куда передается лямбда-выражение? 45
  • 46.
    Решение JET* 46 (p ->(p.size >= bottom && p.size <= top)) lambda$1: код тела лямбды захваченный контекст
  • 47.
    Решение JET* 47 (p ->(p.size >= bottom && p.size <= top)) j.l.Object methods при вызове getClass() , создается класс на лету lambda$1: код тела лямбды захваченный контекст Не нужно создавать класс для большинства случаев
  • 48.
    Лямбды в JET:текущий статус • Пока создаются через indy, но тела лямбд статически компилируются • Классы лямбд динамически компилируются – очень быстро <1ms • В разработке: AOT порождение классов лямбд и их AOT компиляция • В планах: удаление избыточности – класс для лямбды не всегда нужен 48
  • 49.
  • 50.
    Типовые аннотации Могут бытьвезде где есть тип: class TypeAnnotationsExample { @Encrypted String data; List<@NonNull String> strings; HashSet names = (@Immutable HashSet) set; } 50
  • 51.
    Типовые аннотации • Доступныв рантайм через Reflection API: – getTypeAnnotations • Кодируются в Java байткоде атрибутом типа Runtime(In)VisibleTypeAnnotation – новые атрибуты Java 8 байткода 51
  • 52.
    Имена параметров • Еслиjavac задать ключ –parameters, то – в класс-файл будут писаться имена параметров – имена параметров будут доступны через reflection • Используются в Spring MVC 52
  • 53.
    New Java 8APIs 53
  • 54.
    New Java 8APIs • Stream API • Time API • JavaFX 8 • Nashorn Также как и все о 54
  • 55.
    New Java 8APIs • Stream API • Time API • JavaFX 8 • Nashorn Как поддерживаются в JET? 55
  • 56.
    New Java 8APIs • Excelsior – официальный Java SE licensee – лицензируем все исходные тексты Java SE у Oracle – можем поступать с ними как хотим, например компилировать Java байт-код платформы в машинный код и использовать свою реализацию JVM – обязаны проходить тесты на совместимость (JCK) 56
  • 57.
    New Java 8APIs Не все Java 8 APIs одинаково стандартны: • Stream API, Time API входят в стандарт Java 8 • Nashorn, JavaFX НЕ входят в стандарт Java SE – в частности нет тестов JCK 57
  • 58.
  • 59.
    Структура Oracle JRE •Классы Nashorn и JavaFX находятся в папке ext – грузятся Extension класслоадером • Все что находится в папке ext можно официально не включать в Private JRE дистрибутива своего приложения 59
  • 60.
    Распространение приложений скомпилированных ExcelsiorJET • Скомпилированные с помощью Excelsior JET приложения всегда распространяются с приватной копией JET Runtime: – ваши пользователи не должны ставить “Excelsior JRE” – New in Java 8: автоматически НЕ включает JavaFX и Nashorn, если они не используются вашим приложением 60
  • 61.
  • 62.
    Compact Profiles Compact1 Compact2Compact3 java.lang java.rmi java.lang.instrument java.io java.sql java.lang.management java.math javax.transaction javax.management java.nio javax.xml javax.naming java.util org.w3c.dom javax.script java.net org.xml.sax javax.security java.security javax.sql javax.crypto javax.xml.crypto java.text org.ietf.jgss 62
  • 63.
    Compact Profiles • Естьв Java SE Embedded (Linux builds) • В OpenJDK (не собираются на Windows и Mac OS X) 63
  • 64.
    История компонентизации Java SEот Excelsior • Разбиение Java SE на APIs (2000 год) – компиляция их в DLL • JetPerfect (2001 год) – компиляция приложений с нужными частями Java SE в один EXE файл – SWT Example: 1.4 MB • Java Runtime Slim-Down (2007 год) – совместимое с Java SE спецификацией решение • Compact Profiles (2016 год) 64
  • 65.
    История компонентизации Java SEот Sun/Oracle • Kernel JRE (2006 год) • Project Jigsaw 2007 – 2017(?) • Compact Profiles (2014 год) 65
  • 66.
    Compact Profiles • Первыйрабочий и легальный способ уменьшения Private JRE • Есть JCK (тесты совместимости) 66
  • 67.
    Compact Profiles • Первыйрабочий и легальный способ уменьшения Private JRE • Есть JCK (тесты совместимости) • Есть в Excelsior JET для всех десктопных платформ (Windows, Linux, Mac OS X) и в embedded (Linux ARM) 67
  • 68.
    JavaFX on CompactProfiles 68
  • 69.
    JavaFX 8 onCompact Profiles • JavaFX условно состоит из трех логических частей: – Core JavaFX – JavaFX Web (WebKit based) – JavaFX bridges to Swing и SWT 69
  • 70.
    JavaFX 8 onCompact Profiles • Core JavaFX может работать на Compact2 – FXML зависит от XML • JavaFX Swing Bridge требует Full Java SE – Так как очевидно зависит от Swing 70
  • 71.
    JavaFX 8 onCompact Profiles • JavaFX Web тоже имеет зависимости от AWT … 71
  • 72.
    JavaFX 8 onCompact Profiles • JavaFX Web тоже имеет зависимости от AWT, которые не разрешаются во время исполнения ! 72
  • 73.
    JavaFX 8 onCompact Profiles • JavaFX Web тоже имеет зависимости от AWT, которые не разрешаются во время исполнения, кроме одной  … 73
  • 74.
    JavaFX 8 onCompact Profiles • JavaFX Web тоже имеет зависимости от AWT, которые не разрешаются во время исполнения, кроме одной, которая тоже не разрешается в режиме -Xverify:none 74
  • 75.
    JavaFX 8 onCompact Profiles Поддержка JavaFX Web в Excelsior JET: • зависимости от AWT откладываются до разрешения во время исполнения – не разрешаются в статическом компиляторе • Все классы JavaFX верифицируются до исполнения – не требуется верификация во время исполнения и загрузка “лишних” классов • В результате JavaFX Web работает на Compact2! 75
  • 76.
    Java Packager (OracleJDK) vs. JetPackII (Excelsior JET) Java Packager JetPackII with Compact Profiles Ensemble Demo (with WebView sample) 46 MB 21 MB BrickBreaker 42 MB 10 MB 76 Примечание: замеры производились на Windows 32-bit для Java 8 Update 72, представлены размеры дистрибутивов без зависимостей
  • 77.
    Заключение • Java 8– лучший релиз Java со времен Java 5 – лямбды повышают производительность труда • Лямбды не повлияли на спецификацию JVM – но желательна специальная поддержка в JVM • Compact Profiles уменьшают размер Private JRE – важно для магазинов приложений и в embedded • Java != HotSpot 77
  • 78.
    Вопросы и ответы НикитаЛипский, Excelsior [email protected] twitter: @pjBooms 78