103
Семантика final полей в java Владимир Ситников, Валентин Коваленко [email protected], @VladimirSitnikv NetCracker Сентябрь 2014

Семантика final полей в java

Embed Size (px)

DESCRIPTION

Слово final многогранно и многокрасочно. Ни для кого не секрет, что оно может запрещать наследование классов и запрещать изменение значений полей. Более узкому кругу лиц знакомо, что final обладает особыми свойствами при работе нескольких потоков. К сожалению, в сети много мифов о том какие свойства даёт final, и нет внятного толкования почему и как оно работает. Даже на докладах про java memory model final’ы упоминают лишь вскользь. Что же делать? Совсем не использовать final’ы? Это явно не выбор человека, который любит докапываться до истины! В данном докладе мы расставим все точки в слове final, рассмотрим на конкретных примерах как работает раздел 17.5 спецификации языка Java "Final Field Semantics", а также то, какие бывают типичные ошибки в трактовке спецификации.

Citation preview

Page 1: Семантика final полей в java

Семантика final полей в java

Владимир Ситников, Валентин Коваленко[email protected], @VladimirSitnikv

NetCracker

Сентябрь 2014

Page 2: Семантика final полей в java

Введение

Примеры

2 / 103 (c) Copyright 2014, NetCracker Technology Corp. All rights reserved

Page 3: Семантика final полей в java

Зачем final в JMM?

3 / 103 (c) Copyright 2014, NetCracker Technology Corp. All rights reserved

Page 4: Семантика final полей в java

Безопасность String

String s = ...

if (checkAccess(s)) {

return readFile(s);

}

Правильно ли проверяются права на доступ к файлу?

4 / 103 (c) Copyright 2014, NetCracker Technology Corp. All rights reserved

Page 5: Семантика final полей в java

Без опасность String в java 1.4

String s = ...

if (checkAccess(s)) {

return readFile(s);

}

Ответ зависит от версии, и в java 1.4 возможны проблемы

5 / 103 (c) Copyright 2014, NetCracker Technology Corp. All rights reserved

Page 6: Семантика final полей в java

Без опасность String в java 1.4

String s = GLOBAL;

if (checkAccess(s)) {

return readFile(s);

}

HackThread

GLOBAL =

"/tmp/etc/passwd"

.substring (4);

Например: HackThread выполняет .substring(4) и коварнопередаёт его в поток, читающий файлы

6 / 103 (c) Copyright 2014, NetCracker Technology Corp. All rights reserved

Page 7: Семантика final полей в java

Без опасность String в java 1.4

String s = GLOBAL;

if (checkAccess(s)) {

return readFile(s);

}

HackThread

GLOBAL =

"/tmp/etc/passwd"

.substring (4);

В java 1.4 substring-строка ссылается на тот же массивсимволов, и всё опреледяется полями String#offset и String#size

7 / 103 (c) Copyright 2014, NetCracker Technology Corp. All rights reserved

Page 8: Семантика final полей в java

Без опасность String в java 1.4

String s = GLOBAL;

if (checkAccess(s)) {

return readFile(s);

}

HackThread

GLOBAL =

"/tmp/etc/passwd"

.substring (4);

race

race

Синхронизации между потоками нет, поэтому читатель можетувидеть недоинициализированный объект-строку

8 / 103 (c) Copyright 2014, NetCracker Technology Corp. All rights reserved

Page 9: Семантика final полей в java

Без опасность String в java 1.4

String s = GLOBAL;

if (checkAccess(s)) {

return readFile(s);

}

HackThread

GLOBAL =

"/tmp/etc/passwd"

.substring (4);

race

race

checkAccess может увидеть "/tmp/etc/passwd", а readFile уже"/etc/passwd"

Даже синхронизация на s и volatile не спасут!

9 / 103 (c) Copyright 2014, NetCracker Technology Corp. All rights reserved

Page 10: Семантика final полей в java

Без опасность String в java 1.4

String s = GLOBAL;

if (checkAccess(s)) {

return readFile(s);

}

HackThread

GLOBAL =

"/tmp/etc/passwd"

.substring (4);

race

race

checkAccess может увидеть "/tmp/etc/passwd", а readFile уже"/etc/passwd"Даже синхронизация на s и volatile не спасут!

10 / 103 (c) Copyright 2014, NetCracker Technology Corp. All rights reserved

Page 11: Семантика final полей в java

Безопасность String в java 1.5+

String s = GLOBAL;

if (checkAccess(s)) {

return readFile(s);

}

HackThread

GLOBAL =

"/tmp/etc/passwd"

.substring (4);

hb

hb

В java 1.5+ final защищает от недосозданных объектов иHackTread

11 / 103 (c) Copyright 2014, NetCracker Technology Corp. All rights reserved

Page 12: Семантика final полей в java

Зачем нам JMM?

12 / 103 (c) Copyright 2014, NetCracker Technology Corp. All rights reserved

Page 13: Семантика final полей в java

Код-загадка

int x = 1;

public int neverTryThisAtHome () {

int i = this.x; // it is 1, isn’t it?

this.setX (2); // just updates x to 2

return this.x - i; // 2 - 1 == ...?

}

Какие значения могут вернуться? 1? 0? -1?

13 / 103 (c) Copyright 2014, NetCracker Technology Corp. All rights reserved

Page 14: Семантика final полей в java

Код-загадка

int x = 1;

public int neverTryThisAtHome () {

int i = this.x; // it is 1, isn’t it?

this.setX (2); // just updates x to 2

return this.x - i; // 2 - 1 == ...?

}

Да, тут вернётся 1

14 / 103 (c) Copyright 2014, NetCracker Technology Corp. All rights reserved

Page 15: Семантика final полей в java

Код-загадка

final int x = 1;

public int neverTryThisAtHome () {

int i = this.x; // it is 1, isn’t it?

this.setX (2); // just updates x to 2

return this.x - i; // 2 - 1 == ...?

}

А теперь добавим ножек final

15 / 103 (c) Copyright 2014, NetCracker Technology Corp. All rights reserved

Page 16: Семантика final полей в java

Код-загадка

final int x = 1;

public int neverTryThisAtHome () {

int i = this.x; // it is 1, isn’t it?

this.setX (2); // just updates x to 2

return this.x - i; // 2 - 1 == ...?

}

Спецификация разрешает все варианты: 1, 0, и даже -1! (см.пример 17.5.3-1)

16 / 103 (c) Copyright 2014, NetCracker Technology Corp. All rights reserved

Page 17: Семантика final полей в java

Немного теории

17 / 103 (c) Copyright 2014, NetCracker Technology Corp. All rights reserved

Page 18: Семантика final полей в java

Программный порядок (program order)

I Отражает то, в каком порядке написан исходный код

I Компилятору запрещено переупорядочивать, игнорировать именять операции, если это нарушит program order

I Но это не значит, что всё выполняется именно так, как висходном коде

I Например: для операций над локальными переменнымиprogram order вообще не определён

18 / 103 (c) Copyright 2014, NetCracker Technology Corp. All rights reserved

Page 19: Семантика final полей в java

Программный порядок (program order)

I Отражает то, в каком порядке написан исходный кодI Компилятору запрещено переупорядочивать, игнорировать именять операции, если это нарушит program order

I Но это не значит, что всё выполняется именно так, как висходном коде

I Например: для операций над локальными переменнымиprogram order вообще не определён

19 / 103 (c) Copyright 2014, NetCracker Technology Corp. All rights reserved

Page 20: Семантика final полей в java

Программный порядок (program order)

I Отражает то, в каком порядке написан исходный кодI Компилятору запрещено переупорядочивать, игнорировать именять операции, если это нарушит program order

I Но это не значит, что всё выполняется именно так, как висходном коде

I Например: для операций над локальными переменнымиprogram order вообще не определён

20 / 103 (c) Copyright 2014, NetCracker Technology Corp. All rights reserved

Page 21: Семантика final полей в java

Программный порядок (program order)

I Отражает то, в каком порядке написан исходный кодI Компилятору запрещено переупорядочивать, игнорировать именять операции, если это нарушит program order

I Но это не значит, что всё выполняется именно так, как висходном коде

I Например: для операций над локальными переменнымиprogram order вообще не определён

21 / 103 (c) Copyright 2014, NetCracker Technology Corp. All rights reserved

Page 22: Семантика final полей в java

Частичный порядок (partial order)

I В главе 17 JLS 8 раз упоминается слово "partial order"

I Частичным порядкомhb−−→ является бинарное отношение,

которое:

I Рефлексивно: для любого элемента x выполняется xhb−−→ x

I Антисимметрично: если xhb−−→ y и y

hb−−→ x , то x и y это одно и

то же

I Транзитивно: если xhb−−→ y и y

hb−−→ z , то x

hb−−→ z

22 / 103 (c) Copyright 2014, NetCracker Technology Corp. All rights reserved

Page 23: Семантика final полей в java

Частичный порядок (partial order)

I В главе 17 JLS 8 раз упоминается слово "partial order"

I Частичным порядкомhb−−→ является бинарное отношение,

которое:

I Рефлексивно: для любого элемента x выполняется xhb−−→ x

I Антисимметрично: если xhb−−→ y и y

hb−−→ x , то x и y это одно и

то же

I Транзитивно: если xhb−−→ y и y

hb−−→ z , то x

hb−−→ z

23 / 103 (c) Copyright 2014, NetCracker Technology Corp. All rights reserved

Page 24: Семантика final полей в java

Частичный порядок (partial order)

I В главе 17 JLS 8 раз упоминается слово "partial order"

I Частичным порядкомhb−−→ является бинарное отношение,

которое:

I Рефлексивно: для любого элемента x выполняется xhb−−→ x

I Антисимметрично: если xhb−−→ y и y

hb−−→ x , то x и y это одно и

то же

I Транзитивно: если xhb−−→ y и y

hb−−→ z , то x

hb−−→ z

24 / 103 (c) Copyright 2014, NetCracker Technology Corp. All rights reserved

Page 25: Семантика final полей в java

Частичный порядок (partial order)

I В главе 17 JLS 8 раз упоминается слово "partial order"

I Частичным порядкомhb−−→ является бинарное отношение,

которое:

I Рефлексивно: для любого элемента x выполняется xhb−−→ x

I Антисимметрично: если xhb−−→ y и y

hb−−→ x , то x и y это одно и

то же

I Транзитивно: если xhb−−→ y и y

hb−−→ z , то x

hb−−→ z

25 / 103 (c) Copyright 2014, NetCracker Technology Corp. All rights reserved

Page 26: Семантика final полей в java

Частичный порядок (partial order)

I В главе 17 JLS 8 раз упоминается слово "partial order"

I Частичным порядкомhb−−→ является бинарное отношение,

которое:

I Рефлексивно: для любого элемента x выполняется xhb−−→ x

I Антисимметрично: если xhb−−→ y и y

hb−−→ x , то x и y это одно и

то же

I Транзитивно: если xhb−−→ y и y

hb−−→ z , то x

hb−−→ z

26 / 103 (c) Copyright 2014, NetCracker Technology Corp. All rights reserved

Page 27: Семантика final полей в java

Happens-before

I Основной принцип JMM: рассмотрим все возможныевыполнения и откинем "неправильные"

I Happens-before это частичный порядок, который долженсоблюдаться

I Запрещено видеть "будущие" записи (rhb−−→ w)

I И те, которые были перетёрлись в hb порядке:

w1hb−−→ w2

hb−−→ r

I И те, которые запрещены просто так: 17.4.8 executions andcausality requirements

27 / 103 (c) Copyright 2014, NetCracker Technology Corp. All rights reserved

Page 28: Семантика final полей в java

Happens-before

I Основной принцип JMM: рассмотрим все возможныевыполнения и откинем "неправильные"

I Happens-before это частичный порядок, который долженсоблюдаться

I Запрещено видеть "будущие" записи (rhb−−→ w)

I И те, которые были перетёрлись в hb порядке:

w1hb−−→ w2

hb−−→ r

I И те, которые запрещены просто так: 17.4.8 executions andcausality requirements

28 / 103 (c) Copyright 2014, NetCracker Technology Corp. All rights reserved

Page 29: Семантика final полей в java

Happens-before

I Основной принцип JMM: рассмотрим все возможныевыполнения и откинем "неправильные"

I Happens-before это частичный порядок, который долженсоблюдаться

I Запрещено видеть "будущие" записи (rhb−−→ w)

I И те, которые были перетёрлись в hb порядке:

w1hb−−→ w2

hb−−→ r

I И те, которые запрещены просто так: 17.4.8 executions andcausality requirements

29 / 103 (c) Copyright 2014, NetCracker Technology Corp. All rights reserved

Page 30: Семантика final полей в java

Happens-before

I Основной принцип JMM: рассмотрим все возможныевыполнения и откинем "неправильные"

I Happens-before это частичный порядок, который долженсоблюдаться

I Запрещено видеть "будущие" записи (rhb−−→ w)

I И те, которые были перетёрлись в hb порядке:

w1hb−−→ w2

hb−−→ r

I И те, которые запрещены просто так: 17.4.8 executions andcausality requirements

30 / 103 (c) Copyright 2014, NetCracker Technology Corp. All rights reserved

Page 31: Семантика final полей в java

Happens-before

I Основной принцип JMM: рассмотрим все возможныевыполнения и откинем "неправильные"

I Happens-before это частичный порядок, который долженсоблюдаться

I Запрещено видеть "будущие" записи (rhb−−→ w)

I И те, которые были перетёрлись в hb порядке:

w1hb−−→ w2

hb−−→ r

I И те, которые запрещены просто так: 17.4.8 executions andcausality requirements

31 / 103 (c) Copyright 2014, NetCracker Technology Corp. All rights reserved

Page 32: Семантика final полей в java

Семантика final полей одним слайдом

whb−−→ f

hb−−→ a

mc−−→ r1

dr−→ r2⇒ w

hb∗

−−→ r2

I w и r2 – интересующие нас нас запись и чтение

I f – заморозка final поля, которое читается в r1

32 / 103 (c) Copyright 2014, NetCracker Technology Corp. All rights reserved

Page 33: Семантика final полей в java

Семантика final полей одним слайдом

whb−−→ f

hb−−→ a

mc−−→ r1

dr−→ r2⇒ w

hb∗

−−→ r2

I w и r2 – интересующие нас нас запись и чтениеI f – заморозка final поля, которое читается в r1

33 / 103 (c) Copyright 2014, NetCracker Technology Corp. All rights reserved

Page 34: Семантика final полей в java

Семантика final полей одним слайдом

whb−−→ f

hb−−→ a

mc−−→ r1

dr−→ r2⇒ w

hb∗

−−→ r2

I Если единственный путь от записи к чтению идёт через всеэти стрелочки, то мы не можем увидеть более ранние записи

I Если путей больше одного – как повезёт

34 / 103 (c) Copyright 2014, NetCracker Technology Corp. All rights reserved

Page 35: Семантика final полей в java

Семантика final полей одним слайдом

whb−−→ f

hb−−→ a

mc−−→ r1

dr−→ r2⇒ w

hb∗

−−→ r2

I Если единственный путь от записи к чтению идёт через всеэти стрелочки, то мы не можем увидеть более ранние записи

I Если путей больше одного – как повезёт

35 / 103 (c) Copyright 2014, NetCracker Technology Corp. All rights reserved

Page 36: Семантика final полей в java

Freeze action w hb−→ f hb−→ a mc−→ r1 dr−→ r2

Поле

Freezeслучается в конце конструктора и морозит final поля

36 / 103 (c) Copyright 2014, NetCracker Technology Corp. All rights reserved

Page 37: Семантика final полей в java

Freeze action w hb−→ f hb−→ a mc−→ r1 dr−→ r2

Freeze action

Поле

Freezeслучается в конце конструктора и морозит final поля

37 / 103 (c) Copyright 2014, NetCracker Technology Corp. All rights reserved

Page 38: Семантика final полей в java

Freeze action w hb−→ f hb−→ a mc−→ r1 dr−→ r2

Freeze actionПоле

Freezeслучается в конце конструктора и морозит final поля

38 / 103 (c) Copyright 2014, NetCracker Technology Corp. All rights reserved

Page 39: Семантика final полей в java

Dereference chain: что это? w hb−→ f hb−→ a mc−→ r1 dr−→ r2

T local = GLOBAL; r1

int localX = local.x; r2

I r2 читает поле объекта

I Поток не создавал объектI Значит, где-то мы должны были читать адрес этого объекта

I Это называется r1dr−→ r2

39 / 103 (c) Copyright 2014, NetCracker Technology Corp. All rights reserved

Page 40: Семантика final полей в java

Dereference chain: что это? w hb−→ f hb−→ a mc−→ r1 dr−→ r2

T local = GLOBAL; r1

int localX = local.x; r2

I r2 читает поле объектаI Поток не создавал объект

I Значит, где-то мы должны были читать адрес этого объекта

I Это называется r1dr−→ r2

40 / 103 (c) Copyright 2014, NetCracker Technology Corp. All rights reserved

Page 41: Семантика final полей в java

Dereference chain: что это? w hb−→ f hb−→ a mc−→ r1 dr−→ r2

T local = GLOBAL; r1

int localX = local.x; r2

I r2 читает поле объектаI Поток не создавал объектI Значит, где-то мы должны были читать адрес этого объекта

I Это называется r1dr−→ r2

41 / 103 (c) Copyright 2014, NetCracker Technology Corp. All rights reserved

Page 42: Семантика final полей в java

Dereference chain: что это? w hb−→ f hb−→ a mc−→ r1 dr−→ r2

T local = GLOBAL; r1

int localX = local.x; r2

dr

I r2 читает поле объектаI Поток не создавал объектI Значит, где-то мы должны были читать адрес этого объекта

I Это называется r1dr−→ r2

42 / 103 (c) Copyright 2014, NetCracker Technology Corp. All rights reserved

Page 43: Семантика final полей в java

Dereference chain два потока w hb−→ f hb−→ a mc−→ r1 dr−→ r2

Thread 1

T localA = new T();

GLOBAL = localA;

Thread 2

T localB = GLOBAL; r1

if (localB != null) {

int localX = localB.x; r2

}

dr

r1dr−→ r2 (читаем поле несозданного нами объекта)

43 / 103 (c) Copyright 2014, NetCracker Technology Corp. All rights reserved

Page 44: Семантика final полей в java

Dereference chain два потока w hb−→ f hb−→ a mc−→ r1 dr−→ r2

Thread 1

T localA = new T(); a

GLOBAL = localA;

Thread 2

T localB = GLOBAL; r1

if (localB != null) {

int localX = localB.x; r2

}

dr

dr?

Есть ли adr−→ r2?

44 / 103 (c) Copyright 2014, NetCracker Technology Corp. All rights reserved

Page 45: Семантика final полей в java

Dereference chain два потока w hb−→ f hb−→ a mc−→ r1 dr−→ r2

Thread 1

T localA = new T(); a

GLOBAL = localA;

Thread 2

T localB = GLOBAL; r1

if (localB != null) {

int localX = localB.x; r2

}

dr

dr?

Между потоками dr не возникает!

45 / 103 (c) Copyright 2014, NetCracker Technology Corp. All rights reserved

Page 46: Семантика final полей в java

Dereference chain: контрольный выстрелw hb−→ f hb−→ a mc−→ r1 dr−→ r2

T local = GLOBAL; ra

local = GLOBAL; rb

int localX = local.x; r2

Есть ли здесь dr ?

46 / 103 (c) Copyright 2014, NetCracker Technology Corp. All rights reserved

Page 47: Семантика final полей в java

Dereference chain: контрольный выстрелw hb−→ f hb−→ a mc−→ r1 dr−→ r2

T local = GLOBAL; ra

local = GLOBAL; rb

int localX = local.x; r2

dr?

dr?

Один из radr−→ r2 или rb

dr−→ r2 точно должен быть, но точнее

сказать невозможно47 / 103 (c) Copyright 2014, NetCracker Technology Corp. All rights reserved

Page 48: Семантика final полей в java

Memory chain: что это? w hb−→ f hb−→ a mc−→ r1 dr−→ r2

Thread 1

T o = new T();

GL = o; w1

Thread 2

T o = GL; r1

GL2 = o;

Thread 3

T o = GL2;

int r = o.x;

mc

Если чтение видит запись, то w1mc−−→ r1

48 / 103 (c) Copyright 2014, NetCracker Technology Corp. All rights reserved

Page 49: Семантика final полей в java

Memory chain: что это? w hb−→ f hb−→ a mc−→ r1 dr−→ r2

Thread 1

T o = new T();

GL = o; w1

Thread 2

T o = GL; r1

GL2 = o; w2

Thread 3

T o = GL2;

int r = o.x;

mc

mc

Если пишем адрес созданного врагом объекта, то r1mc−−→ w2

49 / 103 (c) Copyright 2014, NetCracker Technology Corp. All rights reserved

Page 50: Семантика final полей в java

Memory chain: что это? w hb−→ f hb−→ a mc−→ r1 dr−→ r2

Thread 1

T o = new T();

GL = o; w1

Thread 2

T o = GL; r1

GL2 = o; w2

Thread 3

T o = GL2; r3

int r = o.x;

mc

mc

mc

r3 видит w2 ⇒ w2mc−−→ r3

50 / 103 (c) Copyright 2014, NetCracker Technology Corp. All rights reserved

Page 51: Семантика final полей в java

Memory chain: что это? w hb−→ f hb−→ a mc−→ r1 dr−→ r2

Thread 1

T o = new T();

GL = o; w1

Thread 2

T o = GL; r1

GL2 = o; w2

Thread 3

T o = GL2; r3

int r = o.x; r4

mc

mc

mc dr

r3dr−→ r4 (читаем поле объекта)

⇒ r3mc−−→ r4

51 / 103 (c) Copyright 2014, NetCracker Technology Corp. All rights reserved

Page 52: Семантика final полей в java

Memory chain: что это? w hb−→ f hb−→ a mc−→ r1 dr−→ r2

Thread 1

T o = new T();

GL = o; w1

Thread 2

T o = GL; r1

GL2 = o; w2

Thread 3

T o = GL2; r3

int r = o.x; r4

mc

mc

mc dr

mc

r3dr−→ r4 (читаем поле объекта) ⇒ r3

mc−−→ r4

52 / 103 (c) Copyright 2014, NetCracker Technology Corp. All rights reserved

Page 53: Семантика final полей в java

Memory chain: что это? w hb−→ f hb−→ a mc−→ r1 dr−→ r2

Thread 1

T o = new T();

GL = o; w1

Thread 2

T o = GL; r1

GL2 = o; w2

Thread 3

T o = GL2; r3

int r = o.x; r4

mc

mc

mc dr

mc

mc

mc транзитивно (т.к. частичный порядок) ⇒ w1mc−−→ r4

53 / 103 (c) Copyright 2014, NetCracker Technology Corp. All rights reserved

Page 54: Семантика final полей в java

Введение

Примеры

54 / 103 (c) Copyright 2014, NetCracker Technology Corp. All rights reserved

Page 55: Семантика final полей в java

Disclaimer

I Все примеры опасно синхронизированы (иначе зачем мысобрались?)

I Случаи чтения null не рассматриваем (даже если онивозможны)

I При составлении слайдов пострадал не один мозг

55 / 103 (c) Copyright 2014, NetCracker Technology Corp. All rights reserved

Page 56: Семантика final полей в java

Disclaimer

I Все примеры опасно синхронизированы (иначе зачем мысобрались?)

I Случаи чтения null не рассматриваем (даже если онивозможны)

I При составлении слайдов пострадал не один мозг

56 / 103 (c) Copyright 2014, NetCracker Technology Corp. All rights reserved

Page 57: Семантика final полей в java

Disclaimer

I Все примеры опасно синхронизированы (иначе зачем мысобрались?)

I Случаи чтения null не рассматриваем (даже если онивозможны)

I При составлении слайдов пострадал не один мозг

57 / 103 (c) Copyright 2014, NetCracker Technology Corp. All rights reserved

Page 58: Семантика final полей в java

Эталонный final (1) w hb−→ f hb−→ a mc−→ r1 dr−→ r2

Thread 1

T l = new T() {{

fx = 42; w

}};

GLOBAL = l;

Thread 2

T o = GLOBAL;

if (o != null) {

int result = o.fx; r2

}

Возможно ли в result получить 0?

58 / 103 (c) Copyright 2014, NetCracker Technology Corp. All rights reserved

Page 59: Семантика final полей в java

Эталонный final (1) w hb−→ f hb−→ a mc−→ r1 dr−→ r2

Thread 1

T l = new T() {{

fx = 42; w

}}; f

GLOBAL = l; a

Thread 2

T o = GLOBAL;

if (o != null) {

int result = o.fx;

}

hb

hb

Действия в одном потоке образуют happens-before:

whb−−→ f , f

hb−−→ a

59 / 103 (c) Copyright 2014, NetCracker Technology Corp. All rights reserved

Page 60: Семантика final полей в java

Эталонный final (1) w hb−→ f hb−→ a mc−→ r1 dr−→ r2

Thread 1

T l = new T() {{

fx = 42; w

}}; f

GLOBAL = l; a

Thread 2

T o = GLOBAL; r0

if (o != null) {

int result = o.fx;

}

hb

hb

mc

r0 видит запись a :

amc−−→ r0

60 / 103 (c) Copyright 2014, NetCracker Technology Corp. All rights reserved

Page 61: Семантика final полей в java

Эталонный final (1) w hb−→ f hb−→ a mc−→ r1 dr−→ r2

Thread 1

T l = new T() {{

fx = 42; w

}}; f

GLOBAL = l; a

Thread 2

T o = GLOBAL; r0

if (o != null) {

int result = o.fx; r1

}

hb

hb

mc

dr

Поток 2 не создавал объект, r1 читает его поле, а r этоединственное чтение адреса объекта, поэтому dereference chain:

r0dr−→ r1

61 / 103 (c) Copyright 2014, NetCracker Technology Corp. All rights reserved

Page 62: Семантика final полей в java

Эталонный final (1) w hb−→ f hb−→ a mc−→ r1 dr−→ r2

Thread 1

T l = new T() {{

fx = 42; w

}}; f

GLOBAL = l; a

Thread 2

T o = GLOBAL; r0

if (o != null) {

int result = o.fx; r1

}

hb

hb

mc

dr

mc

r0dr−→ r1⇒ r0

mc−−→ r1

62 / 103 (c) Copyright 2014, NetCracker Technology Corp. All rights reserved

Page 63: Семантика final полей в java

Эталонный final (1) w hb−→ f hb−→ a mc−→ r1 dr−→ r2

Thread 1

T l = new T() {{

fx = 42; w

}}; f

GLOBAL = l; a

Thread 2

T o = GLOBAL; r0

if (o != null) {

int result = o.fx; r1

}

hb

hb

mc

mc

mc

amc−−→ r1 ( mc транзитивно)

63 / 103 (c) Copyright 2014, NetCracker Technology Corp. All rights reserved

Page 64: Семантика final полей в java

Эталонный final (1) w hb−→ f hb−→ a mc−→ r1 dr−→ r2

Thread 1

T l = new T() {{

fx = 42; w

}}; f

GLOBAL = l; a

Thread 2

T o = GLOBAL;

if (o != null) {

int result = o.fx; r1 r2

}

hb

hb

mc

dr

Возьмём r2 = r1, тогда r1dr−→ r2 ( dr рефлексивно)

64 / 103 (c) Copyright 2014, NetCracker Technology Corp. All rights reserved

Page 65: Семантика final полей в java

Эталонный final (1) w hb−→ f hb−→ a mc−→ r1 dr−→ r2

Thread 1

T l = new T() {{

fx = 42; w

}}; f

GLOBAL = l; a

Thread 2

T o = GLOBAL;

if (o != null) {

int result = o.fx; r1 r2

}

hb

hb

mc

dr

hb*

Нашли всё необходимое для HB∗:

whb−−→ f

hb−−→ a

mc−−→ r1

dr−→ r2⇒ w

hb∗

−−→ r2

65 / 103 (c) Copyright 2014, NetCracker Technology Corp. All rights reserved

Page 66: Семантика final полей в java

Эталонный final (1) w hb−→ f hb−→ a mc−→ r1 dr−→ r2

Thread 1

T l = new T() {{

fx = 42; w

}}; f

GLOBAL = l; a

Thread 2

T o = GLOBAL;

if (o != null) {

int result = o.fx; r1 r2

}

hb

hb

mc

dr

hb*

(whb∗

−−→ r2)⇒ result ∈ {42}

66 / 103 (c) Copyright 2014, NetCracker Technology Corp. All rights reserved

Page 67: Семантика final полей в java

Массив внутри final (2) w hb−→ f hb−→ a mc−→ r1 dr−→ r2

T l = new T() {{

int[] u = new int [1];

u[0] = 42; w

fx = u;

}};

GLOBAL = l;

T o = GLOBAL;

if (o != null) {

int[] lfx = o.fx;

int result = lfx [0]; r2

}

Возможно ли в result получить 0?

67 / 103 (c) Copyright 2014, NetCracker Technology Corp. All rights reserved

Page 68: Семантика final полей в java

Массив внутри final (2) w hb−→ f hb−→ a mc−→ r1 dr−→ r2

T l = new T() {{

int[] u = new int [1];

u[0] = 42; w

fx = u;

}}; f

GLOBAL = l; a

T o = GLOBAL;

if (o != null) {

int[] lfx = o.fx;

int result = lfx [0]; r2

}

hb

hb

Действия в одном потоке образуют happens-before:

whb−−→ f , f

hb−−→ a

68 / 103 (c) Copyright 2014, NetCracker Technology Corp. All rights reserved

Page 69: Семантика final полей в java

Массив внутри final (2) w hb−→ f hb−→ a mc−→ r1 dr−→ r2

T l = new T() {{

int[] u = new int [1];

u[0] = 42; w

fx = u;

}}; f

GLOBAL = l; a

T o = GLOBAL;

if (o != null) {

int[] lfx = o.fx; r1

int result = lfx [0]; r2

}

hb

hb

mc

r1 видит запись a (т.к. простое final поле):

amc−−→ r1

69 / 103 (c) Copyright 2014, NetCracker Technology Corp. All rights reserved

Page 70: Семантика final полей в java

Массив внутри final (2) w hb−→ f hb−→ a mc−→ r1 dr−→ r2

T l = new T() {{

int[] u = new int [1];

u[0] = 42; w

fx = u;

}}; f

GLOBAL = l; a

T o = GLOBAL;

if (o != null) {

int[] lfx = o.fx; r1

int result = lfx [0]; r2

}

hb

hb

mc

dr

Поток 2 не создавал массив, r2 читает его элемент, r1 этоединственное чтение адреса массива, поэтому dereference chain:

r1dr−→ r2

70 / 103 (c) Copyright 2014, NetCracker Technology Corp. All rights reserved

Page 71: Семантика final полей в java

Массив внутри final (2) w hb−→ f hb−→ a mc−→ r1 dr−→ r2

T l = new T() {{

int[] u = new int [1];

u[0] = 42; w

fx = u;

}}; f

GLOBAL = l; a

T o = GLOBAL;

if (o != null) {

int[] lfx = o.fx; r1

int result = lfx [0]; r2

}

hb

hb

mc

dr

hb*

Нашли всё необходимое для HB∗:

whb−−→ f

hb−−→ a

mc−−→ r1

dr−→ r2⇒ w

hb∗

−−→ r2

71 / 103 (c) Copyright 2014, NetCracker Technology Corp. All rights reserved

Page 72: Семантика final полей в java

Массив внутри final (2) w hb−→ f hb−→ a mc−→ r1 dr−→ r2

T l = new T() {{

int[] u = new int [1];

u[0] = 42; w

fx = u;

}}; f

GLOBAL = l; a

T o = GLOBAL;

if (o != null) {

int[] lfx = o.fx; r1

int result = lfx [0]; r2

}

hb

hb

mc

dr

hb*

(whb∗

−−→ r2)⇒ result ∈ {42}

72 / 103 (c) Copyright 2014, NetCracker Technology Corp. All rights reserved

Page 73: Семантика final полей в java

Массив наоборот (2.1) w hb−→ f hb−→ a mc−→ r1 dr−→ r2

T l = new T() {{

int[] u = new int [1];

fx = u; // (!)

u[0] = 42; w

}};

GLOBAL = l;

T o = GLOBAL;

if (o != null) {

int[] lfx = o.fx;

int result = lfx [0];

}

Возможно ли в result получить 0?

73 / 103 (c) Copyright 2014, NetCracker Technology Corp. All rights reserved

Page 74: Семантика final полей в java

Массив наоборот (2.1) w hb−→ f hb−→ a mc−→ r1 dr−→ r2

T l = new T() {{

int[] u = new int [1];

fx = u; // (!)

u[0] = 42; w

}}; f

GLOBAL = l; a

T o = GLOBAL;

if (o != null) {

int[] lfx = o.fx; r1

int result = lfx [0]; r2

}

hbhb

mc

dr

hb∗

Строим hb∗ так же как и в предыдущем случае

74 / 103 (c) Copyright 2014, NetCracker Technology Corp. All rights reserved

Page 75: Семантика final полей в java

Массив наоборот (2.1) w hb−→ f hb−→ a mc−→ r1 dr−→ r2

T l = new T() {{

int[] u = new int [1];

fx = u; // (!)

u[0] = 42; w

}}; f

GLOBAL = l; a

T o = GLOBAL;

if (o != null) {

int[] lfx = o.fx; r1

int result = lfx [0]; r2

}

hbhb

mc

dr

hb∗

(whb∗

−−→ r2)⇒ result ∈ {42}Результат не зависит от порядка записи final полей!

75 / 103 (c) Copyright 2014, NetCracker Technology Corp. All rights reserved

Page 76: Семантика final полей в java

Утекание this (3) w hb−→ f hb−→ a mc−→ r1 dr−→ r2

Thread 1

T l = new T() {{

fx = 42; w

GLOBAL = this;

}};

Thread 2

T o = GLOBAL;

if (o != null) {

int result = o.fx; r2

}

Возможно ли в result получить 0?

76 / 103 (c) Copyright 2014, NetCracker Technology Corp. All rights reserved

Page 77: Семантика final полей в java

Утекание this (3) w hb−→ f hb−→ a mc−→ r1 dr−→ r2

Thread 1

T l = new T() {{

fx = 42; w

GLOBAL = this; a

}}; f

Thread 2

T o = GLOBAL;

if (o != null) {

int result = o.fx; r2

}

hb

hb

Действия в одном потоке образуют happens-before:

whb−−→ f , a

hb−−→ f

77 / 103 (c) Copyright 2014, NetCracker Technology Corp. All rights reserved

Page 78: Семантика final полей в java

Утекание this (3) w hb−→ f hb−→ a mc−→ r1 dr−→ r2

Thread 1

T l = new T() {{

fx = 42; w

GLOBAL = this; a

}}; f

Thread 2

T o = GLOBAL;

if (o != null) {

int result = o.fx; r2

}

hb

hb

hb?

Но нам-то нужно fhb−−→ a!

78 / 103 (c) Copyright 2014, NetCracker Technology Corp. All rights reserved

Page 79: Семантика final полей в java

Утекание this (3) w hb−→ f hb−→ a mc−→ r1 dr−→ r2

Thread 1

T l = new T() {{

fx = 42; w

GLOBAL = this; a

}}; f

Thread 2

T o = GLOBAL;

if (o != null) {

int result = o.fx; r2

}

hb

hb

hb?

Если ahb−−→ f и f

hb−−→ a, то a = f (антисимметричность hb )

Но публикация ссылки это никак не freeze action!

79 / 103 (c) Copyright 2014, NetCracker Technology Corp. All rights reserved

Page 80: Семантика final полей в java

Утекание this (3) w hb−→ f hb−→ a mc−→ r1 dr−→ r2

Thread 1

T l = new T() {{

fx = 42; w

GLOBAL = this; a

}}; f

Thread 2

T o = GLOBAL;

if (o != null) {

int result = o.fx; r2

}

hb

hb

hb?

Нет hb∗ , поэтому возможны все варианты: result ∈ {0, 42}

80 / 103 (c) Copyright 2014, NetCracker Technology Corp. All rights reserved

Page 81: Семантика final полей в java

Вредительское утекание this (4) w hb−→ f hb−→ a mc−→ r1 dr−→ r2

Thread 1

T l = new T() {{

fx = 42; w

GLb = this;

}};

GLa = l;

Thread 2

T u = GLb;

T o = GLa;

if (o != null) {

int result = o.fx; r2

}

Возможно ли в result получить 0?

81 / 103 (c) Copyright 2014, NetCracker Technology Corp. All rights reserved

Page 82: Семантика final полей в java

Вредительское утекание this (4) w hb−→ f hb−→ a mc−→ r1 dr−→ r2

Thread 1

T l = new T() {{

fx = 42; w

GLb = this; b

}}; f

GLa = l; a

Thread 2

T u = GLb;

T o = GLa;

if (o != null) {

int result = o.fx;

}

hb

hb

hb?

Действия в одном потоке образуют happens-before:

whb−−→ f , f

hb−−→ a

82 / 103 (c) Copyright 2014, NetCracker Technology Corp. All rights reserved

Page 83: Семантика final полей в java

Вредительское утекание this (4) w hb−→ f hb−→ a mc−→ r1 dr−→ r2

Thread 1

T l = new T() {{

fx = 42; w

GLb = this; b

}}; f

GLa = l; a

Thread 2

T u = GLb;

T o = GLa; ra

if (o != null) {

int result = o.fx;

}

hb

hb

hb?

mc

Пусть второй поток увидел GLa, тогда amc−−→ ra!

83 / 103 (c) Copyright 2014, NetCracker Technology Corp. All rights reserved

Page 84: Семантика final полей в java

Вредительское утекание this (4) w hb−→ f hb−→ a mc−→ r1 dr−→ r2

Thread 1

T l = new T() {{

fx = 42; w

GLb = this; b

}}; f

GLa = l; a

Thread 2

T u = GLb; rb

T o = GLa; ra

if (o != null) {

int result = o.fx; r1

}

hb

hb

hb?

mc

dr?

dr?

Где-то должно быть dr : rbdr−→ r1 или ra

dr−→ r1

84 / 103 (c) Copyright 2014, NetCracker Technology Corp. All rights reserved

Page 85: Семантика final полей в java

Вредительское утекание this (4) w hb−→ f hb−→ a mc−→ r1 dr−→ r2

Thread 1

T l = new T() {{

fx = 42; w

GLb = this; b

}}; f

GLa = l; a

Thread 2

T u = GLb; rb

T o = GLa; ra

if (o != null) {

int result = o.fx; r1

}

hb

hb

hb?

mc

dr?

dr

Если rbdr−→ r1, то мы попали, т.к. w

hb∗

−−→ r1 не строится

85 / 103 (c) Copyright 2014, NetCracker Technology Corp. All rights reserved

Page 86: Семантика final полей в java

Вредительское утекание this (4) w hb−→ f hb−→ a mc−→ r1 dr−→ r2

Thread 1

T l = new T() {{

fx = 42; w

GLb = this; b

}}; f

GLa = l; a

Thread 2

T u = GLb; rb

T o = GLa; ra

if (o != null) {

int result = o.fx; r1

}

hb

hb

hb?

mc

dr?

dr

Вывод: если наш поток уже читал объект с незамороженнымиполями, то гарантий final semantics нет!

86 / 103 (c) Copyright 2014, NetCracker Technology Corp. All rights reserved

Page 87: Семантика final полей в java

Reflection in action (5) w hb−→ f hb−→ a mc−→ r1 dr−→ r2

T t = new T() {{

fu = new U();

fu.x = 1; w1

}};

GLOBAL = t;

U w = new U();

w.x = 42; w2

reflectSet(t.fu , w);

Thread 2

T t = GLOBAL;

if (t != null) {

U u = t.fu;

int result = u.x; r2

}

Возможно ли в result получить 0?

87 / 103 (c) Copyright 2014, NetCracker Technology Corp. All rights reserved

Page 88: Семантика final полей в java

Reflection in action (5) w hb−→ f hb−→ a mc−→ r1 dr−→ r2

T t = new T() {{

fu = new U();

fu.x = 1;

}};

GLOBAL = t;

U w = new U();

w.x = 42; w2

reflectSet(t.fu , w);

Thread 2

T t = GLOBAL;

if (t != null) {

U u = t.fu;

int result = u.x; r2

}

hb*?

По-хорошему, нам нужно w2hb∗

−−→ r2 (иначе не запрещено видетьзапись 0 в w.x)

88 / 103 (c) Copyright 2014, NetCracker Technology Corp. All rights reserved

Page 89: Семантика final полей в java

Reflection in action (5) w hb−→ f hb−→ a mc−→ r1 dr−→ r2

T t = new T() {{

fu = new U();

fu.x = 1;

}};

GLOBAL = t;

U w = new U();

w.x = 42; w2

reflectSet(t.fu , w); f2

Thread 2

T t = GLOBAL;

if (t != null) {

U u = t.fu;

int result = u.x; r2

}

hb*?

f2 не подходит для hb∗ : нет подходящего f 2hb−−→ a

89 / 103 (c) Copyright 2014, NetCracker Technology Corp. All rights reserved

Page 90: Семантика final полей в java

Reflection in action (5) w hb−→ f hb−→ a mc−→ r1 dr−→ r2

T t = new T() {{

fu = new U();

fu.x = 1;

}}; f1

GLOBAL = t;

U w = new U();

w.x = 42; w2

reflectSet(t.fu , w); f2

Thread 2

T t = GLOBAL;

if (t != null) {

U u = t.fu;

int result = u.x; r2

}

hb*?

hb?

f1 тоже не подходит для hb∗ : должно быть w2hb−−→ f 1

90 / 103 (c) Copyright 2014, NetCracker Technology Corp. All rights reserved

Page 91: Семантика final полей в java

Reflection in action (5) w hb−→ f hb−→ a mc−→ r1 dr−→ r2

T t = new T() {{

fu = new U();

fu.x = 1;

}}; f1

GLOBAL = t;

U w = new U();

w.x = 42; w2

reflectSet(t.fu , w); f2

Thread 2

T t = GLOBAL;

if (t != null) {

U u = t.fu;

int result = u.x; r2

}

hb*?

hb?

Получается, что чтению r2 не запрещено видеть 0

91 / 103 (c) Copyright 2014, NetCracker Technology Corp. All rights reserved

Page 92: Семантика final полей в java

Reflection in action (5) w hb−→ f hb−→ a mc−→ r1 dr−→ r2

T t = new T() {{

fu = new U();

fu.x = 1;

}}; f1

GLOBAL = t; a

U w = new U();

w.x = 42; w2

reflectSet(t.fu , w); f2

Thread 2

T t = GLOBAL;

if (t != null) {

U u = t.fu;

int result = u.x; r2

}

hb*?

hb?

Итого: после публикации менять final поля опасноresult ∈ {0, 1, 42}

92 / 103 (c) Copyright 2014, NetCracker Technology Corp. All rights reserved

Page 93: Семантика final полей в java

Чиним reflection (5.1) w hb−→ f hb−→ a mc−→ r1 dr−→ r2

T t = new T() {{

fu = new U();

fu.x = 1;

}};

U w = new U();

w.x = 42;

reflectSet(t.fu , w);

GLOBAL = t; a

Thread 2

T t = GLOBAL;

if (t != null) {

U u = t.fu;

int result = u.x;

}

Если публиковать ссылку после всех изменений final полей, товсё работает: result ∈ {1, 42}

93 / 103 (c) Copyright 2014, NetCracker Technology Corp. All rights reserved

Page 94: Семантика final полей в java

Final wrapper (6) w hb−→ f hb−→ a mc−→ r1 dr−→ r2

Thread 1

A a = new O() {{

fx = 42; w

}};

GL = a;

Thread 2

A a = GL;

B = new B() {{

fb = o;

}};

GL2 = b;

Thread 3

B B = GL2;

A a = b.fb;

int r = a.fx; r2

Возможно ли в result получить 0?

94 / 103 (c) Copyright 2014, NetCracker Technology Corp. All rights reserved

Page 95: Семантика final полей в java

Final wrapper (6) w hb−→ f hb−→ a mc−→ r1 dr−→ r2

Thread 1

A a = new O() {{

fx = 42; w

}};

GL = a; wa

Thread 2

A a = GL; ra

B = new B() {{

fb = o; wb

}};

GL2 = b;

Thread 3

B B = GL2;

A a = b.fb; rb

int r = a.fx; r1

mc

mc

rb видит wb ⇒ wbmc−−→ rb

ra видит запись wa : wamc−−→ ra

95 / 103 (c) Copyright 2014, NetCracker Technology Corp. All rights reserved

Page 96: Семантика final полей в java

Final wrapper (6) w hb−→ f hb−→ a mc−→ r1 dr−→ r2

Thread 1

A a = new O() {{

fx = 42; w

}};

GL = a; wa

Thread 2

A a = GL; ra

B = new B() {{

fb = o; wb

}};

GL2 = b;

Thread 3

B B = GL2;

A a = b.fb; rb

int r = a.fx; r1

mc

mc

mc

Поток 2 пишет адрес созданного врагом объекта, поэтому

ramc−−→ wb

96 / 103 (c) Copyright 2014, NetCracker Technology Corp. All rights reserved

Page 97: Семантика final полей в java

Final wrapper (6) w hb−→ f hb−→ a mc−→ r1 dr−→ r2

Thread 1

A a = new O() {{

fx = 42; w

}};

GL = a; wa

Thread 2

A a = GL; ra

B = new B() {{

fb = o; wb

}};

GL2 = b;

Thread 3

B B = GL2;

A a = b.fb; rb

int r = a.fx; r1

mc

mc

mcdr

Поток 3 не создавал объект A, r читает его поле, а rb этоединственное чтение адреса объекта, поэтому dereference chain:

rbdr−→ r1

97 / 103 (c) Copyright 2014, NetCracker Technology Corp. All rights reserved

Page 98: Семантика final полей в java

Final wrapper (6) w hb−→ f hb−→ a mc−→ r1 dr−→ r2

Thread 1

A a = new O() {{

fx = 42; w

}};

GL = a; wa

Thread 2

A a = GL; ra

B = new B() {{

fb = o; wb

}};

GL2 = b;

Thread 3

B B = GL2;

A a = b.fb; rb

int r = a.fx; r1

mc

mc

mcdr

mc

rbdr−→ r1⇒ rb

mc−−→ r1

98 / 103 (c) Copyright 2014, NetCracker Technology Corp. All rights reserved

Page 99: Семантика final полей в java

Final wrapper (6) w hb−→ f hb−→ a mc−→ r1 dr−→ r2

Thread 1

A a = new O() {{

fx = 42; w

}};

GL = a; wa

Thread 2

A a = GL; ra

B = new B() {{

fb = o; wb

}};

GL2 = b;

Thread 3

B B = GL2;

A a = b.fb; rb

int r = a.fx; r1

mc

mc

mc

mc

mc

mc транзитивно (т.к. частичный порядок) ⇒ wamc−−→ r1

99 / 103 (c) Copyright 2014, NetCracker Technology Corp. All rights reserved

Page 100: Семантика final полей в java

Final wrapper (6) w hb−→ f hb−→ a mc−→ r1 dr−→ r2

Thread 1

A a = new O() {{

fx = 42; w

}}; f

GL = a; wa

Thread 2

A a = GL; ra

B = new B() {{

fb = o; wb

}};

GL2 = b;

Thread 3

B B = GL2;

A a = b.fb; rb

int r = a.fx; r1 r2

mc

dr

Возьмём r2 = r1, тогда r1dr−→ r2 ( dr рефлексивно)

100 / 103 (c) Copyright 2014, NetCracker Technology Corp. All rights reserved

Page 101: Семантика final полей в java

Final wrapper (6) w hb−→ f hb−→ a mc−→ r1 dr−→ r2

Thread 1

A a = new O() {{

fx = 42; w

}}; f

GL = a; wa

Thread 2

A a = GL; ra

B = new B() {{

fb = o; wb

}};

GL2 = b;

Thread 3

B B = GL2;

A a = b.fb; rb

int r = a.fx; r1 r2

mc

dr

hb

hb

hb*

Нашли всё необходимое для HB∗:

whb−−→ f

hb−−→ a

mc−−→ r1

dr−→ r2⇒ w

hb∗

−−→ r2101 / 103 (c) Copyright 2014, NetCracker Technology Corp. All rights reserved

Page 102: Семантика final полей в java

Final wrapper (6) w hb−→ f hb−→ a mc−→ r1 dr−→ r2

Thread 1

A a = new O() {{

fx = 42; w

}}; f

GL = a; wa

Thread 2

A a = GL; ra

B = new B() {{

fb = o; wb

}};

GL2 = b;

Thread 3

B B = GL2;

A a = b.fb; rb

int r = a.fx; r1 r2

mc

dr

hb

hb

hb*

(whb∗

−−→ r2)⇒ result ∈ {42}

102 / 103 (c) Copyright 2014, NetCracker Technology Corp. All rights reserved

Page 103: Семантика final полей в java

Вопросы?

103 / 103 (c) Copyright 2014, NetCracker Technology Corp. All rights reserved