Transcript
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


Top Related