77
JVM: краткий курс общей анатомии Никита Липский Владимир Парфиненко Excelsior LLC

JVM: краткий курс общей анатомии

Embed Size (px)

Citation preview

Page 1: JVM: краткий курс общей анатомии

JVM: краткий курс общей анатомии

Никита ЛипскийВладимир Парфиненко

Excelsior LLC

Page 2: JVM: краткий курс общей анатомии

2

Page 3: JVM: краткий курс общей анатомии

3

Page 4: JVM: краткий курс общей анатомии

4

Никита Липский

• Более 20 лет профессиональной карьеры• Инициатор проекта Excelsior JET

– работал над проектом более 16 лет– как идейный вдохновитель– как компиляторный инженер– как руководитель– и много в каких еще ролях

• Open source проекты WebFX и Java ReStart – в свободное от работы время

• twitter: @pjBooms

Page 5: JVM: краткий курс общей анатомии

5

Владимир Парфиненко

• Менее 20 лет профессиональной карьеры• Один из разработчиков Excelsior JET

– Программирую компиляторы• Активно учу студентов в НГУ• twitter: @cypok

Page 6: JVM: краткий курс общей анатомии

6

План доклада

• Java class file and bytecode • Classloading engine• Execution engine: interpretators, JIT, AOT• Meta information access subsystem: reflection, indy, JNI• Threading, exception handling, synchronization• Memory management: heap, allocation, GC• Manageability and Monitoring

Page 7: JVM: краткий курс общей анатомии

7

Java class file & bytecode

Page 8: JVM: краткий курс общей анатомии

8

Java class file • 1 класс <–> 1 класс-файл• Constant Pool

– числа, строки– указатели на классы, методы, поля

• Описание класса– имя– модификаторы– супер класс– супер интерфейсы

– поля– методы– атрибуты

Page 9: JVM: краткий курс общей анатомии

9

Java class file

• Поля, методы тоже имеют атрибуты (например, значения константных полей)

• Главный атрибут метода – это его код: Java байт-код

Page 10: JVM: краткий курс общей анатомии

10

Java bytecode

• Массив инструкций

• Стэк операндов инструкций метода

• Массив локальных переменных (аргументы метода, локальные переменные)

Page 11: JVM: краткий курс общей анатомии

11

Java bytecode

Инструкция берет свои операнды со стэка и кладет результат на стэк. Пример:

0: iload 3 // загрузить на стэк переменную #32: bipush 5 // загрузить на стэк константу 54: iadd // сложить два операнда со стэка и загрузить // на стэк результат5: istore 4 // снять значение со стэка в переменную #4

Page 12: JVM: краткий курс общей анатомии

12

JVM: предисловие

Page 13: JVM: краткий курс общей анатомии

13

Программа для JVM

Любая программа исполняемая на JVM имеет?

Page 14: JVM: краткий курс общей анатомии

14

Программа для JVM

Любая программа исполняемая на JVM имеет:• main класс

public static void main(String[] args)• сlasspath – список директорий и архивов (jar файлов)

• В мире веб приложений программа для JVM – это веб сервер– Tomcat, GlassFish и т.п.

Page 15: JVM: краткий курс общей анатомии

15

Java Runtime

Для исполнения программы на JVM одной JVM не достаточно. Нужен Java Runtime Environment:• JVM• Платформенные классы

– core классы (j.l.Object, j.l.String и т.д.)– Java standard APIs (IO, NET, NIO, AWT/Swing и т.д)

• Реализация нативных методов платформенных классов (OS specific)• Вспомогательные файлы (описатели временных зон, медиа ресурсы

и т.п.)

Page 16: JVM: краткий курс общей анатомии

16

Анатомия JVM

OS

+ CP

U

MonitoringAOT

Bytecode

Classloading

engineBytecode Verification

Execution engine:interpreter, JIT

ThreadingSynchronization

Metainformation

Memory management,Garbage Collection

Native methods

Page 17: JVM: краткий курс общей анатомии

17

Classloading engine

OS

+ CP

U

MonitoringAOT

Bytecode

Execution engine:interpreter, JIT

ThreadingSynchronization

Metainformation

Memory management,Garbage Collection

Native methods

Page 18: JVM: краткий курс общей анатомии

18

Загрузка классов

• Где JVM берет классы для исполнения:

– Из Java Runtime (платформенные классы)

– Из classpath приложения

– Авто-сгенеренные на лету (Proxy, Reflection accessors, реализация invoke dynamic)

– Предоставленные самим приложением

Page 19: JVM: краткий курс общей анатомии

19

Загрузка классов

• Каждый класс грузится каким-то загрузчиком классов:– Платформенные классы грузятся bootstrap загрузчиком– Классы из classpath приложения – системным загрузчиком

(AppClassLoader) – Классы приложения могут создавать свои загрузчики, которые

будут грузить классы

Page 20: JVM: краткий курс общей анатомии

20

Загрузка классов

• Каждый класс грузится каким-то загрузчиком классов:– Платформенные классы грузятся bootstrap загрузчиком– Классы из classpath приложения – системным загрузчиком

(AppClassLoader) – Классы приложения могут создавать свои загрузчики, которые

будут грузить классы • Загрузчик классов образует уникальное пространство имен

классов

Page 21: JVM: краткий курс общей анатомии

21

Старт JVM

• Грузится main класс системным загрузчиком (из classpath приложения)– Провоцирует загрузку части платформенных классов (core)

• Исполняется метод main(String[] args)

Page 22: JVM: краткий курс общей анатомии

22

Процесс загрузки класса (создание класса)

• Читается class file – Проверяется корректность формата (может выбросить

ClassFormatError)• Создается ран-тайм представление класса в выделенной

области памяти – runtime constant pool in Method Area aka Meta Space aka

Permanent Generation• Грузятся суперкласс, суперинтерфейсы

Page 23: JVM: краткий курс общей анатомии

23

Линковка

• Верификация байт-кода

• Подготовка

• Разрешение символьных ссылок

Page 24: JVM: краткий курс общей анатомии

C: StackOverflowError

A: Программа зациклится B: VerifyError

D: Байт-код не исполнится

Что произойдет при исполнении этого байт-кода?

0: bipush 22: bipush 24: iadd5: goto 0

Page 25: JVM: краткий курс общей анатомии

25

Верификация байт-кода

• Происходит с классом один раз• Проверка корректности инструкций (корректности

переходов)• Проверка выхода за пределы стэка операндов и локальных

переменных• Проверка совместимости типов

Page 26: JVM: краткий курс общей анатомии

26

Верификация байт-кода

• Верификация методом вывода типов (type inference verification)– Потоковый анализ: итеративное уточнение типовой информации

до достижения неподвижной точки

• Раздельная (split) верификация (type checking verification)– Неподвижная точка для потокового анализа кодируется внутрь

байт-кода специальным атрибутом. Т.о. верификация происходит за один проход

Page 27: JVM: краткий курс общей анатомии

27

Разрешение символьных ссылок

Класс может иметь ссылки на другие классы и поля, методы других классов

• Ленивое разрешение – ссылки разрешаются при первом доступе

• Энергичное разрешение– разрешаются все ссылки какие возможно

Page 28: JVM: краткий курс общей анатомии

28

Инициализация класса

• Вызов статического инициализатора класса

• Случается при first use:– new– доступ до статического поля– вызов статического метода

• Провоцирует инициализацию супер-класса и супер-интерфейсов с default методами

Page 29: JVM: краткий курс общей анатомии

29

Execution engine

OS

+ CP

U

Monitoring

Bytecode

Classloading

engine

Execution engine:interpreter, JIT

ThreadingSynchronization

Metainformation

Memory management,Garbage Collection

Native methods

Bytecode Verification

AOT

Page 30: JVM: краткий курс общей анатомии

30

Исполнение Java байт-кода

JVM может исполнять байт-код двумя способам:

• Интерпретировать

• Транслировать в машинный код, который будет исполняться непосредственно на CPU

Page 31: JVM: краткий курс общей анатомии

31

Интерпретатор

pc = 0;do { fetch opcode at pc; if (operands) fetch operands; execute the opcode; calculate pc;} while (there is more to do);

Page 32: JVM: краткий курс общей анатомии

32

Компиляторы• Неоптимизирующие

– “что вижу, то пою”

• Простые оптимизирующие (пример HotSpot Client)– Простое внутреннее представление (IR)– Простые оптимизации– Pros: быстрая компиляция

• Сложные оптимизирующие (пример HotSpot Server)– Сложный IR, более мощные оптимизации– Pros: более оптимальный код

Page 33: JVM: краткий курс общей анатомии

33

• Динамические (Just-In-Time – JIT). – Трансляция в машинный код происходит во время

исполнения программы

• Статические (Ahead-Of-Time – AOT)– Трансляция происходит до исполнения программы

Компиляторы

Page 34: JVM: краткий курс общей анатомии

34

Динамические компиляторы (JIT)

• Работают одновременно с исполняемой программой• Компилируют горячий код• Горячий код вычисляется с помощью динамического

профилировщика• Используют информацию времени

исполнения для оптимизаций

Page 35: JVM: краткий курс общей анатомии

35

Статические компиляторы (AOT)

• Не ограничены в ресурсах для оптимизации программ

• Компилируют каждый метод программы применяя самые агрессивные оптимизации

• На оптимизацию не тратятся ресурсы во время исполнения программы (быстрее старт)

Page 36: JVM: краткий курс общей анатомии

36

Статические компиляторы (AOT)

Интересный факт:Во время работы статически скомпилированной Java программы может не исполниться ни одного Java байт-кода.

Вопрос: а где JVM?

Page 37: JVM: краткий курс общей анатомии

37

Meta information subsystem

OS

+ CP

U

MonitoringAOT

Bytecode

Classloading

engineBytecode Verification

Execution engine:interpreter, JIT

ThreadingSynchronization

Metainformation

Memory management,Garbage Collection

Native methods

Page 38: JVM: краткий курс общей анатомии

38

Reflection

• Позволяет доступаться до классов, полей, методов по имени из Java программы

• Реализуется в JVM через доступ в Meta space

• Ключевая возможность Java для многих популярных фреймворков и реализаций языков на JVM

Page 39: JVM: краткий курс общей анатомии

39

Method Handles and invokedynamic (JSR-292, indy)

• Indy: программируемый вызов– для эффективной реализации динамических языков на JVM

• MethodHandle – целевой объект вызова через invokedynamic – может быть доступом к полю, методу– комбинацией других MethodHandle– может использоваться отдельно от indy: Reflection 2.0

Page 40: JVM: краткий курс общей анатомии

40

Java native interface (JNI)

• Связывает JVM c внешним миром (OS)

• Си интерфейс к JVM– Не зависит от реализации JVM– Используется для реализации native методов на языке С (или другом

системном языке)– С помощью JNI написаны платформенно-зависимые реализации Java SE API: IO, NET, AWT

• Реализуется в JVM как доступ к Meta space

Page 41: JVM: краткий курс общей анатомии

41

Threading and synchronization

OS

+ CP

U

MonitoringAOT

Bytecode

Classloading

engineBytecode Verification

Execution engine:interpreter, JIT

ThreadingSynchronization

Metainformation

Memory management,Garbage Collection

Native methods

Page 42: JVM: краткий курс общей анатомии

42

java.lang.Thread

• Java поток мапируется на нативный поток в соотношение 1-1

• С потоком связана память используемая для локальных переменных и стэка операндов методов (фреймов методов): стэк (stack)– Размер стэка – параметр JVM: -Xss

• Имеет информацию о стэке вызовов методов потока (stack trace)– В любой момент может о нем рассказать

Page 43: JVM: краткий курс общей анатомии

43

Обработка исключений

Знание о стэке вызовов помогает в обработке исключений:

method 7throw

method 3catch

method 6

. . .

method 2

. . .

method 3catch

method 2

. . .

PC

PC

exception caught

Page 44: JVM: краткий курс общей анатомии

44

Потоки и Java Memory Model

// Thread 1:Shared.data = getData();Shared.ready = true;

// Thread 2:while (!Shared.ready) { // wait}receivedData = Shared.data;

Page 45: JVM: краткий курс общей анатомии

46

Синхронизация

• Для безопасного доступа к разделяемой памяти между потоками

• В наивной реализации используются средства ОС– ОС монитор есть в каждом Java объекте как скрытое поле

• Оптимизирована когда конкуренция за ресурс происходит много реже, чем вход в synchronized

Page 46: JVM: краткий курс общей анатомии

47

Memory management

OS

+ CP

U

MonitoringAOT

Bytecode

Classloading

engineBytecode Verification

Execution engine:interpreter, JIT

ThreadingSynchronization

Metainformation

Memory management,Garbage Collection

Native methods

Page 47: JVM: краткий курс общей анатомии

48

Выделение памяти

• Реализация оператора new

• Объекты выделенные с помощью оператора new располагаются в т.н. куче (Java heap)

• Организация Java heap JVM-cпецифична• Разметка (layout) Java объекта тоже JVM специфична.

Page 48: JVM: краткий курс общей анатомии

49

Java heap

Внутренняя топология Java кучи сильно зависит от алгоритма GC. В разных реализациях может делиться на:

• Область молодого и старого поколения• Разбиваться на блоки• Большие объекты могут управляться особым образом

Page 49: JVM: краткий курс общей анатомии

50

Аллокация объектов

• Должна быть быстрой– JVM запрашивает у OC память не под один объект, а сразу на

много – Аллокация методом продвижения границы

• Потоко-безопасной (thread-safe), но при этом параллельной (не блокирующей)– Thread local heaps: каждый поток “грызет” свой кусок памяти

Page 50: JVM: краткий курс общей анатомии

51

Layout Java объекта

Не специфицируется JVM, но по факту требует:• Java Object header

– Указатель на класс– Монитор (lock)– Identity hashcode– Флаги для GC

• Поля– Могут быть переупорядочены из соображений экономии размера,

выравнивания, особенностей целевой архитектуры

Page 51: JVM: краткий курс общей анатомии

52

Сборка мусора

Page 52: JVM: краткий курс общей анатомии

53

Сборка мусора

Page 53: JVM: краткий курс общей анатомии

54

Что такое мусор?

Page 54: JVM: краткий курс общей анатомии

55

Что такое мусор?

Page 55: JVM: краткий курс общей анатомии

56

Что такое мусор?

Page 56: JVM: краткий курс общей анатомии

57

Что такое мусор?

Page 57: JVM: краткий курс общей анатомии

58

Мусор

Мусором являются объекты, которые не могут использоваться программой

Вопрос: А какие объекты могут использоваться?

Page 58: JVM: краткий курс общей анатомии

59

Мусор

Мусором являются объекты, которые не могут использоваться программой

Вопрос: А какие объекты могут использоваться?

Ответ: Не мусор!

Page 59: JVM: краткий курс общей анатомии

60

Не мусор

1. Объекты в статических полях классов

2. В локальных переменных

3. … всё?

Page 60: JVM: краткий курс общей анатомии

61

Не мусор

Object o = new Object();...

GC случился здесь!

Page 61: JVM: краткий курс общей анатомии

62

Не мусор 2

1. Объекты в статических полях классов

2. В локальных переменныхДоступных из фрейма метода (локальные переменные и стэк операндов)

Какого метода?

Page 62: JVM: краткий курс общей анатомии

63

Не мусор

Page 63: JVM: краткий курс общей анатомии

64

Не мусор 2 возвращается

1. Объекты в статических полях классов

2. В локальных переменныхДоступных из фрейма метода фреймов методов (локальные переменные и стэк операндов) стэка вызовов всех Java потоков.

3. Объекты, на которые ссылается “не мусор”

Page 64: JVM: краткий курс общей анатомии

65

Корневое множество объектов (GC roots)

1. Объекты в статических полях классов

2. Объекты доступные со стэка Java потоков

3. Объекты из JNI ссылок в native методах

Page 65: JVM: краткий курс общей анатомии

66

Не мусор 3

Не мусор aka живые объекты – это:

1. Объекты из корневого множества

2. Объекты, на которые ссылаются живые объекты

Все остальное – мусор.

Page 66: JVM: краткий курс общей анатомии

67

Трассирующие сборщики

• Mark-and-sweep– Помечает живые объекты (mark), “выметает” (удаляет) мусор

(sweep)

• Stop-and-copy– Копирует живые объекты в специальное место (copy) – Освободившиеся место (мусор и места где были живые объекты)

может использоваться для новой аллокации

Page 67: JVM: краткий курс общей анатомии

68

Stop the World

• Живые объекты определены для определенного момента исполнения программы– При исполнении множество меняется

• Чтобы собрать мусор в общем случае нужно остановить потоки, чтобы определить где мусор (STW пауза)

Page 68: JVM: краткий курс общей анатомии

69

Stop the World

Одна из основных задач современных сборщиков мусора – это уменьшение времени STW паузы. Методы уменьшения:• Инкрементальный

– собирать не весь мусор в паузе• Параллельный

– собирать мусор во многих потоках в паузе• Одновременный (concurrent)

– собирать мусор одновременно с работой программы (не останавливая потоки)

Page 69: JVM: краткий курс общей анатомии

70

Поколенная сборка мусора

Гипотеза о поколениях: большинство объектов умирает молодыми

Поколенный (generational) GC:• частный вид инкрементального• во время т.н. малых сборок удаляем мусор среди молодых

объектов• объекты, пережившие одну или несколько сборок, перемещаем

в область старого поколения

Page 70: JVM: краткий курс общей анатомии

71

GC: advanced topics

• Финализаторы и слабые ссылки• GC (safe) points• Точные vs. консервативные GC• Способы борьбы с фрагментацией кучи• Real time GC• Class GC• Базовые алгоритмы GC• Конкретные реализации:

– В одной HotSpot JVM пять(!) разных GC

Page 71: JVM: краткий курс общей анатомии

72

Manageability & Monitoring

OS

+ CP

U

MonitoringAOT

Bytecode

Classloading

engineBytecode Verification

Execution engine:interpreter, JIT

ThreadingSynchronization

Metainformation

Memory management,Garbage Collection

Native methods

Page 72: JVM: краткий курс общей анатомии

73

Manageability & Monitoring

JVM знает про вашу программу всё:• про все загруженные классы• про все живые объекты• про все потоки• про все исполняемые методы потоков

Почему бы не поделиться с вами этой информацией во время исполнения?

Page 73: JVM: краткий курс общей анатомии

74

Manageability & Monitoring

JVM Tool Interface (JVM TI):• отладчики • профилировщики

Java Management Beans:• Инструменты мониторинга запущенных приложений

– JConsole, JMX console, AMC – Visual VM– Java Mission Control

Page 74: JVM: краткий курс общей анатомии

75

Абстрактная JVM

OS

+ CP

U

MonitoringAOT

Bytecode

Classloading

engineBytecode Verification

Execution engine:interpreter, JIT

ThreadingSynchronization

Metainformation

Memory management,Garbage Collection

Native methods

Page 75: JVM: краткий курс общей анатомии

76

Реализации JVM

Совместимые с Java SE спецификацией:• Oracle HotSpot • Oracle JRockit (RIP)• IBM J9• Excelsior JET• Azul (HotSpot based, но свой GC)• SAP, RedHat (свои порты HotSpot на разные платформы)

Page 76: JVM: краткий курс общей анатомии

77

Заключение• JVM сложная, но жутко интересная штука

• Java – золотая середина современных IT технологий:– Подробно специфицирована– Эффективность помноженная на гибкость:

• типизированность Java байт-кода позволяет его транслировать в машинный код очень эффективно

• при этом reflection, indy, динамическая загрузка придает платформе высокую гибкость и динамичность

• Все реализации JVM в постоянном развитии на острие науки и технологий

Page 77: JVM: краткий курс общей анатомии

78

Вопросы и ответы

Никита Липский,Excelsior

[email protected]: @pjBooms

Владимир Парфиненко,Excelsior

[email protected]: @cypok