SlideShare a Scribd company logo
AOT компиляция Java 
Никита Липский 
Excelsior 
1
Давным давно 
2
Давным давно, 
Во времена С+++ 
++++++ 
3
Давным давно, 
Во времена С+++, 
Все компиляторы 
были статические 
++++++ 4
Пока не 
появилась.. 
5
Пока не появилась 
Java 
6
Исполнение 
Java байткода JVM 
• Интерпретация 
• Компиляция в машинный код и исполнение 
на “железе” 
7
Трансляция Java to Native 
• Динамическая (Just-In-Time – JIT). 
– Трансляция происходит во время исполнения 
программы 
• Статическая (Ahead-Of-Time – AOT) 
– Трансляция происходит до исполнения 
программы 
8
9
Статическая компиляция Java 
• Это вообще возможно? 
– Если да, то при каких условиях и будет ли это все еще 
называться Java? 
• Зачем это нужно? 
– Обфускация vs. статическая компиляция 
– Старт приложения 
– Уменьшение размера дистрибутива Java приложения 
без зависимостей от Java 
– Производительность: какие преимущества перед JIT 
компиляцией 
– Почему AOT лучше для Desktop, Embedded, Mobile 
– Есть ли выгода от применения AOT на server side 
10
11
Кому нужен AOT для Java? 
ККттоо ззннааеетт ппрроо Excelsior JET? 
12
Мифы вокруг статической 
компиляции Java 
13
Java - «слишком» динамическая 
• Reflection 
Миф 1. 
• Динамическая загрузка 
Статическая компиляция невозможна? 
14
Миф 2. AOT компиляция – 
убийца WORA 
WORA: Write Once Run Anywhere 
(пиши раз, исполняй везде) 
!= 
BORA: Build Once? 
(собирай раз??? …) 
15
Миф 3. AOT = маленький Exe 
”Я получу (маленький) исполняемый файл, 
который будет работать без JVM (как в 
С)” 
Но: 
– Стандартные классы? 
– GC, reflection? 
16
Миф 3. AOT = маленький Exe 
Тем не менее, используя AOT, можно 
получить дистрибутив Java приложения 
без зависимостей от Java значительно 
меньший, чем размер JRE: 
“Javа худеет”: 
http://www.youtube.com/watch?v=CKWlp8UQQb4 
17
Java «слишком» динамическая 
18
Нестандартные загрузчики классов 
• Переопределяют умолчательную логику 
разрешений ссылок между классами 
• Уникальное пространство имен 
• Позволяют управлять зависимостями, решая 
проблемы JAR hell (OSGi, Java Module System) 
• Java EE сервера, Eclipse RCP, плагины 
19
Нестандартные загрузчики классов 
Как компилировать статически? 
• Компилировать каждый класс изолировано 
от других 
– Плохо для производительности 
• Изучить логику разрешения ссылок для 
популярных загрузчиков 
– Не работает для произвольных загрузчиков 
20
Нестандартные загрузчики классов 
Classes 
21
Нестандартные загрузчики классов 
Classes 
CL1 
CL2 
CL3 
CL4 
CLi: classloader (загрузчик классов) 22
Нестандартные загрузчики классов 
• CL1 • CL2 
classes classes 
classes classes 
• CL3 • CL4 
23
Нестандартные загрузчики классов 
• CL1 • CL2 
classes 
classes 
classes classes 
• CL3 • CL4 
24
Нестандартные загрузчики классов 
• CL1 • CL2 
classes classes 
classes classes 
• CL3 • CL4 
25
Нестандартные загрузчики классов 
• CL1 • CL2 
– Картинка 
classes classes 
classes 
• CL3 • CL4 
26
Нестандартные загрузчики классов 
• CL1 • CL2 
classes classes 
• CL3 • CL4 
27
Нестандартные загрузчики классов 
Схема поддержки загрузчиков в AOT: 
• Компонента разрешения ссылок в AOT 
компиляторе: 
– Определяет, какие загрузчики будут созданы 
во время исполнения и назначается каждому 
статический ID 
– Разбивает классы приложения по загрузчикам 
– Разрешает ссылки между классами 
28
Нестандартные загрузчики классов 
Схема поддержки загрузчиков в AOT: 
• Во время исполнения: 
– По экземпляру загрузчика вычисляется ID 
– Имея статический ID, мы можем грузить 
статически скомпилированные классы: 
• создание экземпляра класса java.lang.Class 
• наполнение его рефлективной информацией 
• загрузка кода осуществляется OS 
29
Зачем AOT для Java? 
30
Защита кода от декомпиляции 
31
Защита кода приложения 
• Java bytecode легко превращается в 
исходный код 
• Процесс обфускации при активном 
использовании reflection трудоемок и 
трудно поддерживаем 
• Даже по обфусцированному коду часто 
можно понять, что код делает (ссылки на 
JDK остаются в неизменном виде) 
32
Защита кода приложения 
• Машинный код можно только эффективно 
дизассемблировать 
• По дизассемблированному коду не понять 
структуру приложения (нет имен классов, 
методов) 
• После агрессивной оптимизации 
машинный код далек от оригинального 
кода 
33
Время старта приложения 
34
Холодный старт vs теплый 
Во второй раз приложение стартует 
значительно быстрее, чем в первый 
– Загрузка кода и данных приложения с диска 
– Загрузка системных и сторонних динамических 
библиотек (dll, so) 
35
Java Quick Start 
• Java Quick Start 
– Предзагружает rt.jar, динамические библиотеки 
36
AOT быстрее? 
• Машинный код “толще” Java bytecode 
• Загрузка кода с диска занимает больше 
времени, чем его начальное исполнение 
37
AOT быстрее! 
• Код исполняемый на старте – в начало 
исполняемого файла 
• Можно предзагружать стартовый сегмент 
последовательным чтением 
38
39
Производительность 
40
Миф 4. AOT быстрее 
“Скомпилировав Java статически, мы 
получим скорость приложения как в C, C 
быстрее Java, следовательно AOT быстрее” 
41
Миф 5. JIT быстрее 
“Эффективно оптимизировать Java 
приложения можно только на основе 
динамического профиля исполнения” 
42
Виды оптимизаций 
– Протяжка констант 
– Удаление избыточного кода 
– Удаление общих 
подвыражений 
– Открытая подстановка 
– Специализация методов 
– Развертывание циклов 
– Версионирование циклов 
– Вынос инвариантов 
– Удаление хвостовой 
рекурсии 
– Девиртуализация вызовов 
– Аллокация объектов на 
стэке и их взрыв 
– Удаление проверок 
времени исполнения 
– Удаление избыточной 
синхронизации 
– Оптимальная выборка 
кода и свертка 
шаблонов 
– Планировка 
инструкций 
– Оптимальное 
распределение 
регистров 
43
Java – ООП 
• Много методов 
• Методы маленькие (get/set) 
• Методы по умолчанию ВИРТУАЛЬНЫЕ 
44
Девиртуализация вызовов 
• Предусловие дальнейшей открытой подстановки 
(inline) 
• Анализ иерархии классов 
– метод не перегружается – невиртуальный 
• Типовый анализ 
– new T().foo(); //вызов foo() 
невиртуальный 
• Inline caches 
45
Анализ иерархии классов (CHA) 
Идея: метод не перегружается – невиртуальный 
A a; 
… 
 
a.foo(); 
if (RT_Type(a) in CHA) { 
inlined body of foo() 
} else { 
a.foo(); 
} 
46
Идея: 
Типовый анализ 
new A().foo(); //невиртуальный вызов 
47
Типовый анализ 
A a = b? new B() : new C(); 
a.foo(); 
Если foo() в B и С один и тоже, то 
a.foo() невиртуальный вызов 
(можно инлайнить) 
48
Типовый анализ 
A a = b? bar() : baz(); 
… 
a.foo(); 
Если bar() возвращает только new B, 
а baz() экземпляры new С, то 
a.foo() - опять невиртуальный вызов 
(можно инлайнить) 
49
Типовый анализ 
Откуда мы знаем, что возвращает bar() и 
baz()? 
50
Глобальный анализ 
• Глобальный анализ – анализирует все 
методы программы, вычисляя про каждый 
метод полезную информацию 
• Результаты глобального анализа 
используются для оптимизации 
конкретного метода 
51
Аллокация объектов 
на стэке 
• Все Java объекты создаются в динамической 
памяти – Java heap (куча) 
• Большинство объектов временные 
• Хочется их размещать на стэке метода 
• Escape анализ (анализ утечек) – определяет 
утекает ли объект в разделяемую память. 
52
void foo() { 
for (Object o: getCollection()) { 
doSomething(o); 
} 
} 
Пример 
53
void foo() { 
Iterator iter = getCollection().iterator(); 
while (iter.hasNext()) { 
Object o = iter.next(); 
doSomething(o); 
} 
} 
Пример 
54
void foo() { 
ArrayList list = getCollection(); 
Iterator iter = list.iterator(); 
while (iter.hasNext()) { 
Object o = iter.next(); 
doSomething(o); 
} 
} 
Пример 
55
void foo() { 
ArrayList list = getCollection(); 
ArrayList.ListItr iter = new ListItr(list); 
while (iter.hasNext()) { 
Object o = iter.next(); 
doSomething(o); 
} 
} 
Пример 
56
void foo() { 
ArrayList list = getCollection(); 
ArrayList.ListItr iter = onStack ListItr(); 
iter.this$0 = list; 
iter.cursor = 0; 
iter.size = list.elemData.length; 
while (iter.hasNext()) { 
Object o = iter.next(); 
doSomething(o); 
} 
} 
Пример 
57
void foo() { 
ArrayList list = getCollection(); 
ArrayList.ListItr iter = onStack ListItr(list); 
iter.this$0 = list; 
iter.cursor = 0; 
iter.size = list.elemData.length; 
while (iter.cursor < iter.size) { 
int index = iter.cursor++; 
Object o = iter.this$0.elemData[index]; 
doSomething(o); 
} 
} 
Пример 
58
void foo() { 
ArrayList list = getCollection(); 
int cursor = 0; 
int size = list.elemData.length; 
while (cursor < size) { 
Object o = list.elemData[cursor++]; 
doSomething(o); 
} 
} 
Пример 
59
void foo() { 
ArrayList list = getCollection(); 
int size = list.elemData.length; 
for (int i = 0; i < size; i++) { 
doSomething(list.elemData[i]); 
} 
} 
Пример 
60
Анализ и оптимизации 
• Часто бывают довольно сложными 
• Требуют итеративного пересчета 
• Глобальный анализ зависит от ВСЕЙ программы. 
61
Анализ и оптимизации 
• Часто бывают довольно сложными 
• Требуют итеративного пересчета 
• Глобальный анализ зависит от ВСЕЙ программы. 
Все ли это может 
себе позволить JIT? 
62
Анализ и оптимизации 
• Часто бывают довольно сложными 
• Требуют итеративного пересчета 
• Глобальный анализ зависит от ВСЕЙ программы. 
Все ли это может 
себе позволить JIT? 
63
Анализ и оптимизации 
• Часто бывают довольно сложными 
• Требуют итеративного пересчета 
• Глобальный анализ зависит от ВСЕЙ программы. 
Все ли это может 
себе позволить JIT? 
64
Динамические оптимизации 
• Профилировка и селективная компиляция 
• Открытая подстановка на основе профиля 
исполнения 
• Оптимизация трасс исполнения 
• Выбор оптимальных инструкций 
65
Горячий код vs теплый 
• А что будет, если у приложения нет ярко 
выраженного горячего кода? 
• Долгий прогрев, результаты прогрева не 
используются при дальнейших стартах 
приложения 
66
Динамические оптимизации 
Может ли статический компилятор 
использовать динамический профиль 
исполнения? 
67
Server side 
• Процессорное время в 
облаках – дорого 
• Через некоторое время работы сервера 
профиль исполнения стабилизируется 
• Почему этот профиль не передать 
статическому компилятору? 
68
Не кодом единым … 
• Кроме кода приложения, есть еще код JVM 
– Управление памятью 
– Сборка мусора 
– Потоки и синхронизация 
– Обработка исключительных ситуаций 
– … 
• Кроме Java кода, есть сторонний код 
– Native методы + нативные библиотеки (в т.ч. ОС) 
69
Embedded 
• Чем слабее железо, тем дороже 
динамическая компиляция 
• Встроенные системы часто не обладают 
теми же вычислительными мощностями, 
что и настольные компьютеры/сервера 
70
Mobile 
• JVM on Mobile: 
71
Mobile 
• JVM on Mobile: 
– Платформенные классы 
72
Mobile 
• JVM on Mobile: 
– Платформенные классы 
– GC и Memory Manager 
73
Mobile 
• JVM on Mobile: 
– Платформенные классы 
– GC и Memory Manager 
– Reflection 
74
Mobile 
• JVM on Mobile: 
– Платформенные классы 
– GC и Memory Manager 
– Reflection 
– JIT 
75
Mobile 
• JVM on Mobile: 
– Платформенные классы 
– GC и Memory Manager 
– Reflection 
– JIT 
Чего не хватает? 
76
Mobile 
• JVM on Mobile: 
– Платформенные классы 
– GC и Memory Manager 
– Reflection 
– JIT 
Зарядки! 
77
Mobile 
• У беспроводных устройств есть БАТАРЕЙКА 
• Стоит ли ее тратить на динамическую 
компиляцию? 
78
iOS 
• Политика распространения приложений на 
iOS запрещает любую динамическую 
загрузку кода 
• Для Java возможен либо интерпретатор, 
либо AOT 
79
AOT компиляторы для Java 
GCJ 
Excelsior JET 
Android ART 
RoboVM 
Avian 
CodeNameOne 
IBM J9 
Java ME 
80
81
Итоги 
Статическая компиляция Java 
• возможна 
– с сохранением всех возможностей Java 
– даже в присутствии нестандартных загрузчиков классов 
• полезна 
– для защиты кода 
– быстрого старта 
– лучшего UX 
– улучшения производительности 
– экономии батарейки, памяти, диска 
82
Вопросы и ответы 
Никита Липский, 
Excelsior 
nlipsky@excelsior-usa.com 
twitter: @pjBooms 
83
Ускорение приложений 
84

More Related Content

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

What's hot (20)

PDF
Разговор про Java 9. Extended version
PDF
What to expect from Java 9
PDF
Java худеет. Спроси меня как.
PPTX
Java 9 модули
PPTX
Верификация Java байткода: когда, как, а может отключить?
PDF
Как сделать ваш JavaScript быстрее / Роман Дворнов (Авито)
PDF
Java осень 2014 занятие 1
PPTX
Основы и нюансы параллельного тестрования
PDF
Готовимся к Java SE 7 Programmer: от новичка до профессионала за 45 дней
PPTX
Sql server clr integration
PPTX
Практический опыт использования некоторых современных решений репликации MySQL
PPTX
Использование Open Source инструментов для автоматизации тестирования
PDF
Ангелы и демоны многопоточного программирования / Алексей Федоров (Одноклассн...
PPTX
Тестируем производительность распределённых систем, Александр Киров (Parallels)
PPTX
Автоматизация тестирования многопоточности
PDF
Tech Talks @NSU: AOT-компиляция Java
PPTX
Введение в Akka
PDF
DC/OS – больше чем PAAS, Никита Борзых (Express 42)
PPTX
Зачем нужна Scala?
PPTX
Система обработки бизнес-логики server-side приложения на Groovy
Разговор про Java 9. Extended version
What to expect from Java 9
Java худеет. Спроси меня как.
Java 9 модули
Верификация Java байткода: когда, как, а может отключить?
Как сделать ваш JavaScript быстрее / Роман Дворнов (Авито)
Java осень 2014 занятие 1
Основы и нюансы параллельного тестрования
Готовимся к Java SE 7 Programmer: от новичка до профессионала за 45 дней
Sql server clr integration
Практический опыт использования некоторых современных решений репликации MySQL
Использование Open Source инструментов для автоматизации тестирования
Ангелы и демоны многопоточного программирования / Алексей Федоров (Одноклассн...
Тестируем производительность распределённых систем, Александр Киров (Parallels)
Автоматизация тестирования многопоточности
Tech Talks @NSU: AOT-компиляция Java
Введение в Akka
DC/OS – больше чем PAAS, Никита Борзых (Express 42)
Зачем нужна Scala?
Система обработки бизнес-логики server-side приложения на Groovy
Ad

Viewers also liked (10)

PPT
Секреты сборки мусора в Java
PPTX
TestNG vs JUnit: cease fire or the end of the war
PPT
Lec 2 Java
PDF
WDB005.1 - JavaScript for Java Developers (Lecture 1)
PPTX
Java Core. Lecture# 1. Intro
PDF
Keynote on JavaDay Omsk 2014 about new features in Java 8
PPTX
Expert Java Day: Java concurrency
PPTX
Классы и объекты в Java
PDF
Date & Time in Java SE 8
ODP
Java: вчера, сегодня, завтра
Секреты сборки мусора в Java
TestNG vs JUnit: cease fire or the end of the war
Lec 2 Java
WDB005.1 - JavaScript for Java Developers (Lecture 1)
Java Core. Lecture# 1. Intro
Keynote on JavaDay Omsk 2014 about new features in Java 8
Expert Java Day: Java concurrency
Классы и объекты в Java
Date & Time in Java SE 8
Java: вчера, сегодня, завтра
Ad

Similar to Java Ahead-Of-Time compilation (20)

PDF
AOT-компиляция Java
PDF
CodeFest 2012. Липский Н. — JIT vs. AOT. Единство и борьба динамического и ст...
PDF
Java Platform Performance BoF
PPTX
2014.12.23 Александр Андреев, Parallels
PDF
How to cook a blockchain and not get burned
PDF
20100307 virtualization igotti_lecture05
PDF
20100314 virtualization igotti_lecture06
PPTX
Построение собственного JS SDK — зачем и как?
PDF
Java 9: what is there beyond modularization
PDF
Н. Иготти. Виртуализация и виртуальные машины. Лекция 02
ODP
Java 9 - Back to the Future
PDF
Память в Java. Garbage Collector
PDF
Zero Downtime PHP Deployment with Envoyer And Forge
PDF
In the sun.misc.Unsafe bowels
PPTX
TMPA-2013 Petrenko Pakulin: Technical Solutions and Non-Technical Challenges ...
PPTX
Dz Java Hi Load 0.4
PDF
Дмитрий Юницкий. «Android NDK или как я перестал бояться и полюбил нативную р...
PPTX
Что могут статические анализаторы, чего не могут программисты и тестировщики
PPTX
Оптимизация производительности нагруженных веб-систем на Java
PDF
PostgreSQL performance recipes
AOT-компиляция Java
CodeFest 2012. Липский Н. — JIT vs. AOT. Единство и борьба динамического и ст...
Java Platform Performance BoF
2014.12.23 Александр Андреев, Parallels
How to cook a blockchain and not get burned
20100307 virtualization igotti_lecture05
20100314 virtualization igotti_lecture06
Построение собственного JS SDK — зачем и как?
Java 9: what is there beyond modularization
Н. Иготти. Виртуализация и виртуальные машины. Лекция 02
Java 9 - Back to the Future
Память в Java. Garbage Collector
Zero Downtime PHP Deployment with Envoyer And Forge
In the sun.misc.Unsafe bowels
TMPA-2013 Petrenko Pakulin: Technical Solutions and Non-Technical Challenges ...
Dz Java Hi Load 0.4
Дмитрий Юницкий. «Android NDK или как я перестал бояться и полюбил нативную р...
Что могут статические анализаторы, чего не могут программисты и тестировщики
Оптимизация производительности нагруженных веб-систем на Java
PostgreSQL performance recipes

More from Nikita Lipsky (12)

PPTX
Escaping The Jar hell with Jigsaw Layers
PDF
JIT Versus AOT: Unity And Conflict of Dynamic and Static Compilers (JavaOne 2...
PPTX
Java 9 Modules: The Duke Yet Lives That OSGi Shall Depose
PDF
AOT для Java: Мифы и Challenges
PPTX
JIT vs. AOT: Unity And Conflict of Dynamic and Static Compilers
PPTX
Ahead-Of-Time Compilation of Java Applications
PPTX
Delivering Native User Experience In Client Side Java Applications
PPTX
Java Restart with WebFX
PDF
Веб 3.0. Есть ли будущее у Java в RIA и Mobile?
PDF
Занимательные истории из жизни технической поддержки JVM
PPTX
Неумолимая близость десктопа, веба и мобайла
PPT
История одной JVM в картинках
Escaping The Jar hell with Jigsaw Layers
JIT Versus AOT: Unity And Conflict of Dynamic and Static Compilers (JavaOne 2...
Java 9 Modules: The Duke Yet Lives That OSGi Shall Depose
AOT для Java: Мифы и Challenges
JIT vs. AOT: Unity And Conflict of Dynamic and Static Compilers
Ahead-Of-Time Compilation of Java Applications
Delivering Native User Experience In Client Side Java Applications
Java Restart with WebFX
Веб 3.0. Есть ли будущее у Java в RIA и Mobile?
Занимательные истории из жизни технической поддержки JVM
Неумолимая близость десктопа, веба и мобайла
История одной JVM в картинках

Java Ahead-Of-Time compilation

  • 1. AOT компиляция Java Никита Липский Excelsior 1
  • 3. Давным давно, Во времена С+++ ++++++ 3
  • 4. Давным давно, Во времена С+++, Все компиляторы были статические ++++++ 4
  • 7. Исполнение Java байткода JVM • Интерпретация • Компиляция в машинный код и исполнение на “железе” 7
  • 8. Трансляция Java to Native • Динамическая (Just-In-Time – JIT). – Трансляция происходит во время исполнения программы • Статическая (Ahead-Of-Time – AOT) – Трансляция происходит до исполнения программы 8
  • 9. 9
  • 10. Статическая компиляция Java • Это вообще возможно? – Если да, то при каких условиях и будет ли это все еще называться Java? • Зачем это нужно? – Обфускация vs. статическая компиляция – Старт приложения – Уменьшение размера дистрибутива Java приложения без зависимостей от Java – Производительность: какие преимущества перед JIT компиляцией – Почему AOT лучше для Desktop, Embedded, Mobile – Есть ли выгода от применения AOT на server side 10
  • 11. 11
  • 12. Кому нужен AOT для Java? ККттоо ззннааеетт ппрроо Excelsior JET? 12
  • 13. Мифы вокруг статической компиляции Java 13
  • 14. Java - «слишком» динамическая • Reflection Миф 1. • Динамическая загрузка Статическая компиляция невозможна? 14
  • 15. Миф 2. AOT компиляция – убийца WORA WORA: Write Once Run Anywhere (пиши раз, исполняй везде) != BORA: Build Once? (собирай раз??? …) 15
  • 16. Миф 3. AOT = маленький Exe ”Я получу (маленький) исполняемый файл, который будет работать без JVM (как в С)” Но: – Стандартные классы? – GC, reflection? 16
  • 17. Миф 3. AOT = маленький Exe Тем не менее, используя AOT, можно получить дистрибутив Java приложения без зависимостей от Java значительно меньший, чем размер JRE: “Javа худеет”: http://www.youtube.com/watch?v=CKWlp8UQQb4 17
  • 19. Нестандартные загрузчики классов • Переопределяют умолчательную логику разрешений ссылок между классами • Уникальное пространство имен • Позволяют управлять зависимостями, решая проблемы JAR hell (OSGi, Java Module System) • Java EE сервера, Eclipse RCP, плагины 19
  • 20. Нестандартные загрузчики классов Как компилировать статически? • Компилировать каждый класс изолировано от других – Плохо для производительности • Изучить логику разрешения ссылок для популярных загрузчиков – Не работает для произвольных загрузчиков 20
  • 22. Нестандартные загрузчики классов Classes CL1 CL2 CL3 CL4 CLi: classloader (загрузчик классов) 22
  • 23. Нестандартные загрузчики классов • CL1 • CL2 classes classes classes classes • CL3 • CL4 23
  • 24. Нестандартные загрузчики классов • CL1 • CL2 classes classes classes classes • CL3 • CL4 24
  • 25. Нестандартные загрузчики классов • CL1 • CL2 classes classes classes classes • CL3 • CL4 25
  • 26. Нестандартные загрузчики классов • CL1 • CL2 – Картинка classes classes classes • CL3 • CL4 26
  • 27. Нестандартные загрузчики классов • CL1 • CL2 classes classes • CL3 • CL4 27
  • 28. Нестандартные загрузчики классов Схема поддержки загрузчиков в AOT: • Компонента разрешения ссылок в AOT компиляторе: – Определяет, какие загрузчики будут созданы во время исполнения и назначается каждому статический ID – Разбивает классы приложения по загрузчикам – Разрешает ссылки между классами 28
  • 29. Нестандартные загрузчики классов Схема поддержки загрузчиков в AOT: • Во время исполнения: – По экземпляру загрузчика вычисляется ID – Имея статический ID, мы можем грузить статически скомпилированные классы: • создание экземпляра класса java.lang.Class • наполнение его рефлективной информацией • загрузка кода осуществляется OS 29
  • 31. Защита кода от декомпиляции 31
  • 32. Защита кода приложения • Java bytecode легко превращается в исходный код • Процесс обфускации при активном использовании reflection трудоемок и трудно поддерживаем • Даже по обфусцированному коду часто можно понять, что код делает (ссылки на JDK остаются в неизменном виде) 32
  • 33. Защита кода приложения • Машинный код можно только эффективно дизассемблировать • По дизассемблированному коду не понять структуру приложения (нет имен классов, методов) • После агрессивной оптимизации машинный код далек от оригинального кода 33
  • 35. Холодный старт vs теплый Во второй раз приложение стартует значительно быстрее, чем в первый – Загрузка кода и данных приложения с диска – Загрузка системных и сторонних динамических библиотек (dll, so) 35
  • 36. Java Quick Start • Java Quick Start – Предзагружает rt.jar, динамические библиотеки 36
  • 37. AOT быстрее? • Машинный код “толще” Java bytecode • Загрузка кода с диска занимает больше времени, чем его начальное исполнение 37
  • 38. AOT быстрее! • Код исполняемый на старте – в начало исполняемого файла • Можно предзагружать стартовый сегмент последовательным чтением 38
  • 39. 39
  • 41. Миф 4. AOT быстрее “Скомпилировав Java статически, мы получим скорость приложения как в C, C быстрее Java, следовательно AOT быстрее” 41
  • 42. Миф 5. JIT быстрее “Эффективно оптимизировать Java приложения можно только на основе динамического профиля исполнения” 42
  • 43. Виды оптимизаций – Протяжка констант – Удаление избыточного кода – Удаление общих подвыражений – Открытая подстановка – Специализация методов – Развертывание циклов – Версионирование циклов – Вынос инвариантов – Удаление хвостовой рекурсии – Девиртуализация вызовов – Аллокация объектов на стэке и их взрыв – Удаление проверок времени исполнения – Удаление избыточной синхронизации – Оптимальная выборка кода и свертка шаблонов – Планировка инструкций – Оптимальное распределение регистров 43
  • 44. Java – ООП • Много методов • Методы маленькие (get/set) • Методы по умолчанию ВИРТУАЛЬНЫЕ 44
  • 45. Девиртуализация вызовов • Предусловие дальнейшей открытой подстановки (inline) • Анализ иерархии классов – метод не перегружается – невиртуальный • Типовый анализ – new T().foo(); //вызов foo() невиртуальный • Inline caches 45
  • 46. Анализ иерархии классов (CHA) Идея: метод не перегружается – невиртуальный A a; …  a.foo(); if (RT_Type(a) in CHA) { inlined body of foo() } else { a.foo(); } 46
  • 47. Идея: Типовый анализ new A().foo(); //невиртуальный вызов 47
  • 48. Типовый анализ A a = b? new B() : new C(); a.foo(); Если foo() в B и С один и тоже, то a.foo() невиртуальный вызов (можно инлайнить) 48
  • 49. Типовый анализ A a = b? bar() : baz(); … a.foo(); Если bar() возвращает только new B, а baz() экземпляры new С, то a.foo() - опять невиртуальный вызов (можно инлайнить) 49
  • 50. Типовый анализ Откуда мы знаем, что возвращает bar() и baz()? 50
  • 51. Глобальный анализ • Глобальный анализ – анализирует все методы программы, вычисляя про каждый метод полезную информацию • Результаты глобального анализа используются для оптимизации конкретного метода 51
  • 52. Аллокация объектов на стэке • Все Java объекты создаются в динамической памяти – Java heap (куча) • Большинство объектов временные • Хочется их размещать на стэке метода • Escape анализ (анализ утечек) – определяет утекает ли объект в разделяемую память. 52
  • 53. void foo() { for (Object o: getCollection()) { doSomething(o); } } Пример 53
  • 54. void foo() { Iterator iter = getCollection().iterator(); while (iter.hasNext()) { Object o = iter.next(); doSomething(o); } } Пример 54
  • 55. void foo() { ArrayList list = getCollection(); Iterator iter = list.iterator(); while (iter.hasNext()) { Object o = iter.next(); doSomething(o); } } Пример 55
  • 56. void foo() { ArrayList list = getCollection(); ArrayList.ListItr iter = new ListItr(list); while (iter.hasNext()) { Object o = iter.next(); doSomething(o); } } Пример 56
  • 57. void foo() { ArrayList list = getCollection(); ArrayList.ListItr iter = onStack ListItr(); iter.this$0 = list; iter.cursor = 0; iter.size = list.elemData.length; while (iter.hasNext()) { Object o = iter.next(); doSomething(o); } } Пример 57
  • 58. void foo() { ArrayList list = getCollection(); ArrayList.ListItr iter = onStack ListItr(list); iter.this$0 = list; iter.cursor = 0; iter.size = list.elemData.length; while (iter.cursor < iter.size) { int index = iter.cursor++; Object o = iter.this$0.elemData[index]; doSomething(o); } } Пример 58
  • 59. void foo() { ArrayList list = getCollection(); int cursor = 0; int size = list.elemData.length; while (cursor < size) { Object o = list.elemData[cursor++]; doSomething(o); } } Пример 59
  • 60. void foo() { ArrayList list = getCollection(); int size = list.elemData.length; for (int i = 0; i < size; i++) { doSomething(list.elemData[i]); } } Пример 60
  • 61. Анализ и оптимизации • Часто бывают довольно сложными • Требуют итеративного пересчета • Глобальный анализ зависит от ВСЕЙ программы. 61
  • 62. Анализ и оптимизации • Часто бывают довольно сложными • Требуют итеративного пересчета • Глобальный анализ зависит от ВСЕЙ программы. Все ли это может себе позволить JIT? 62
  • 63. Анализ и оптимизации • Часто бывают довольно сложными • Требуют итеративного пересчета • Глобальный анализ зависит от ВСЕЙ программы. Все ли это может себе позволить JIT? 63
  • 64. Анализ и оптимизации • Часто бывают довольно сложными • Требуют итеративного пересчета • Глобальный анализ зависит от ВСЕЙ программы. Все ли это может себе позволить JIT? 64
  • 65. Динамические оптимизации • Профилировка и селективная компиляция • Открытая подстановка на основе профиля исполнения • Оптимизация трасс исполнения • Выбор оптимальных инструкций 65
  • 66. Горячий код vs теплый • А что будет, если у приложения нет ярко выраженного горячего кода? • Долгий прогрев, результаты прогрева не используются при дальнейших стартах приложения 66
  • 67. Динамические оптимизации Может ли статический компилятор использовать динамический профиль исполнения? 67
  • 68. Server side • Процессорное время в облаках – дорого • Через некоторое время работы сервера профиль исполнения стабилизируется • Почему этот профиль не передать статическому компилятору? 68
  • 69. Не кодом единым … • Кроме кода приложения, есть еще код JVM – Управление памятью – Сборка мусора – Потоки и синхронизация – Обработка исключительных ситуаций – … • Кроме Java кода, есть сторонний код – Native методы + нативные библиотеки (в т.ч. ОС) 69
  • 70. Embedded • Чем слабее железо, тем дороже динамическая компиляция • Встроенные системы часто не обладают теми же вычислительными мощностями, что и настольные компьютеры/сервера 70
  • 71. Mobile • JVM on Mobile: 71
  • 72. Mobile • JVM on Mobile: – Платформенные классы 72
  • 73. Mobile • JVM on Mobile: – Платформенные классы – GC и Memory Manager 73
  • 74. Mobile • JVM on Mobile: – Платформенные классы – GC и Memory Manager – Reflection 74
  • 75. Mobile • JVM on Mobile: – Платформенные классы – GC и Memory Manager – Reflection – JIT 75
  • 76. Mobile • JVM on Mobile: – Платформенные классы – GC и Memory Manager – Reflection – JIT Чего не хватает? 76
  • 77. Mobile • JVM on Mobile: – Платформенные классы – GC и Memory Manager – Reflection – JIT Зарядки! 77
  • 78. Mobile • У беспроводных устройств есть БАТАРЕЙКА • Стоит ли ее тратить на динамическую компиляцию? 78
  • 79. iOS • Политика распространения приложений на iOS запрещает любую динамическую загрузку кода • Для Java возможен либо интерпретатор, либо AOT 79
  • 80. AOT компиляторы для Java GCJ Excelsior JET Android ART RoboVM Avian CodeNameOne IBM J9 Java ME 80
  • 81. 81
  • 82. Итоги Статическая компиляция Java • возможна – с сохранением всех возможностей Java – даже в присутствии нестандартных загрузчиков классов • полезна – для защиты кода – быстрого старта – лучшего UX – улучшения производительности – экономии батарейки, памяти, диска 82
  • 83. Вопросы и ответы Никита Липский, Excelsior nlipsky@excelsior-usa.com twitter: @pjBooms 83