Transcript
Page 1: Final field semantics

Semantics of final fields in java

Vladimir Sitnikov, Valentin [email protected], @VladimirSitnikv

NetCracker

September 2014

Page 2: Final field semantics

Introduction

Examples

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

Page 3: Final field semantics

Why final is required inJMM?

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

Page 4: Final field semantics

String safety

String s = ...

if (checkAccess(s)) {

return readFile(s);

}

Is this a valid security check?

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

Page 5: Final field semantics

String unsafety in 1.4

String s = ...

if (checkAccess(s)) {

return readFile(s);

}

The answer depends on the java version, and in java 1.4 the code isinsecure

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

Page 6: Final field semantics

String unsafety in 1.4

String s = GLOBAL;

if (checkAccess(s)) {

return readFile(s);

}

HackThread

GLOBAL =

"/tmp/etc/passwd"

.substring (4);

For instance: HackThread executes .substring(4) and transfers itvia data race to the checker thread

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

Page 7: Final field semantics

String unsafety in 1.4

String s = GLOBAL;

if (checkAccess(s)) {

return readFile(s);

}

HackThread

GLOBAL =

"/tmp/etc/passwd"

.substring (4);

In java 1.4 result of substring references the same char array, andthe value depends on String#offset and String#size

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

Page 8: Final field semantics

String unsafety in 1.4

String s = GLOBAL;

if (checkAccess(s)) {

return readFile(s);

}

HackThread

GLOBAL =

"/tmp/etc/passwd"

.substring (4);

race

race

Since no synchronization is in place, reader might observenot-fully-initialized String

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

Page 9: Final field semantics

String unsafety in 1.4

String s = GLOBAL;

if (checkAccess(s)) {

return readFile(s);

}

HackThread

GLOBAL =

"/tmp/etc/passwd"

.substring (4);

race

race

checkAccess might observe "/tmp/etc/passwd", and even thenreadFile might observe "/etc/passwd"

Even synchronization on s and volatile will not help!

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

Page 10: Final field semantics

String unsafety in 1.4

String s = GLOBAL;

if (checkAccess(s)) {

return readFile(s);

}

HackThread

GLOBAL =

"/tmp/etc/passwd"

.substring (4);

race

race

checkAccess might observe "/tmp/etc/passwd", and even thenreadFile might observe "/etc/passwd"Even synchronization on s and volatile will not help!

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

Page 11: Final field semantics

String safety in java 1.5+

String s = GLOBAL;

if (checkAccess(s)) {

return readFile(s);

}

HackThread

GLOBAL =

"/tmp/etc/passwd"

.substring (4);

hb

hb

In java 1.5+ final protects from such non-initialized objects fromHackThread

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

Page 12: Final field semantics

Зачем нам JMM?

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

Page 13: Final field semantics

Quiz

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 == ...?

}

What is the result? 1? 0? -1?

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

Page 14: Final field semantics

Quiz

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 == ...?

}

OK, the result is 1

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

Page 15: Final field semantics

Quiz

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 == ...?

}

Let’s add some final

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

Page 16: Final field semantics

Quiz

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 == ...?

}

The specification allows all the cases: 1, 0, and even -1! (see alsoexample 17.5.3-1)

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

Page 17: Final field semantics

A bit of theory

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

Page 18: Final field semantics

Program order

I Program order is a total order among inter-thread actions ofeach thread in source code order

I Compiler is forbidden to reorder/alter/ignore operations ifobservable behavior violates program order

I It does not mean the program is executed in program orderI For instance: program order is not defined for operations onlocal variables

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

Page 19: Final field semantics

Program order

I Program order is a total order among inter-thread actions ofeach thread in source code order

I Compiler is forbidden to reorder/alter/ignore operations ifobservable behavior violates program order

I It does not mean the program is executed in program orderI For instance: program order is not defined for operations onlocal variables

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

Page 20: Final field semantics

Program order

I Program order is a total order among inter-thread actions ofeach thread in source code order

I Compiler is forbidden to reorder/alter/ignore operations ifobservable behavior violates program order

I It does not mean the program is executed in program order

I For instance: program order is not defined for operations onlocal variables

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

Page 21: Final field semantics

Program order

I Program order is a total order among inter-thread actions ofeach thread in source code order

I Compiler is forbidden to reorder/alter/ignore operations ifobservable behavior violates program order

I It does not mean the program is executed in program orderI For instance: program order is not defined for operations onlocal variables

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

Page 22: Final field semantics

Partial order

I In section 17 JLS "partial order" is mentioned 8 times

I Partial order ishb−−→ a binary relation that is:

I Reflexive: for each element x , xhb−−→ x

I Antisymmetric: if xhb−−→ y and y

hb−−→ x , then x and y are the same

element

I Transitive: if xhb−−→ y and y

hb−−→ z , then x

hb−−→ z

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

Page 23: Final field semantics

Partial order

I In section 17 JLS "partial order" is mentioned 8 times

I Partial order ishb−−→ a binary relation that is:

I Reflexive: for each element x , xhb−−→ x

I Antisymmetric: if xhb−−→ y and y

hb−−→ x , then x and y are the same

element

I Transitive: if xhb−−→ y and y

hb−−→ z , then x

hb−−→ z

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

Page 24: Final field semantics

Partial order

I In section 17 JLS "partial order" is mentioned 8 times

I Partial order ishb−−→ a binary relation that is:

I Reflexive: for each element x , xhb−−→ x

I Antisymmetric: if xhb−−→ y and y

hb−−→ x , then x and y are the same

element

I Transitive: if xhb−−→ y and y

hb−−→ z , then x

hb−−→ z

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

Page 25: Final field semantics

Partial order

I In section 17 JLS "partial order" is mentioned 8 times

I Partial order ishb−−→ a binary relation that is:

I Reflexive: for each element x , xhb−−→ x

I Antisymmetric: if xhb−−→ y and y

hb−−→ x , then x and y are the same

element

I Transitive: if xhb−−→ y and y

hb−−→ z , then x

hb−−→ z

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

Page 26: Final field semantics

Partial order

I In section 17 JLS "partial order" is mentioned 8 times

I Partial order ishb−−→ a binary relation that is:

I Reflexive: for each element x , xhb−−→ x

I Antisymmetric: if xhb−−→ y and y

hb−−→ x , then x and y are the same

element

I Transitive: if xhb−−→ y and y

hb−−→ z , then x

hb−−→ z

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

Page 27: Final field semantics

Happens-before

I General idea of JMM: let’s consider all the executions and forbid"bad" ones

I Happens-before is a partial order that selects allowable readsI A read either sees the latest write (in hb order)I Or any write via data race when multiple writes are

hb -unordered with the readI It must still obey other rules, especially: 17.4.8 executions andcausality requirements

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

Page 28: Final field semantics

Happens-before

I General idea of JMM: let’s consider all the executions and forbid"bad" ones

I Happens-before is a partial order that selects allowable reads

I A read either sees the latest write (in hb order)I Or any write via data race when multiple writes are

hb -unordered with the readI It must still obey other rules, especially: 17.4.8 executions andcausality requirements

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

Page 29: Final field semantics

Happens-before

I General idea of JMM: let’s consider all the executions and forbid"bad" ones

I Happens-before is a partial order that selects allowable readsI A read either sees the latest write (in hb order)

I Or any write via data race when multiple writes arehb -unordered with the read

I It must still obey other rules, especially: 17.4.8 executions andcausality requirements

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

Page 30: Final field semantics

Happens-before

I General idea of JMM: let’s consider all the executions and forbid"bad" ones

I Happens-before is a partial order that selects allowable readsI A read either sees the latest write (in hb order)I Or any write via data race when multiple writes are

hb -unordered with the read

I It must still obey other rules, especially: 17.4.8 executions andcausality requirements

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

Page 31: Final field semantics

Happens-before

I General idea of JMM: let’s consider all the executions and forbid"bad" ones

I Happens-before is a partial order that selects allowable readsI A read either sees the latest write (in hb order)I Or any write via data race when multiple writes are

hb -unordered with the readI It must still obey other rules, especially: 17.4.8 executions andcausality requirements

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

Page 32: Final field semantics

Semantics of final fields

whb−−→ f

hb−−→ a

mc−−→ r1

dr−→ r2⇒ w

hb∗

−−→ r2

I w and r2 – the read and the write in question

I f – freeze of a final field, that is read in r1

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

Page 33: Final field semantics

Semantics of final fields

whb−−→ f

hb−−→ a

mc−−→ r1

dr−→ r2⇒ w

hb∗

−−→ r2

I w and r2 – the read and the write in questionI f – freeze of a final field, that is read in r1

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

Page 34: Final field semantics

Semantics of final fields

whb−−→ f

hb−−→ a

mc−−→ r1

dr−→ r2⇒ w

hb∗

−−→ r2

I If the only path from write to read follows all this arrows, thenwe must not see earlier writes

I If multiple paths exist, you need to go deeperI We use hb∗ notation to distinguish it from hb and since "thishappens-before ordering does not transitively close with otherhappens-before orderings"

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

Page 35: Final field semantics

Semantics of final fields

whb−−→ f

hb−−→ a

mc−−→ r1

dr−→ r2⇒ w

hb∗

−−→ r2

I If the only path from write to read follows all this arrows, thenwe must not see earlier writes

I If multiple paths exist, you need to go deeper

I We use hb∗ notation to distinguish it from hb and since "thishappens-before ordering does not transitively close with otherhappens-before orderings"

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

Page 36: Final field semantics

Semantics of final fields

whb−−→ f

hb−−→ a

mc−−→ r1

dr−→ r2⇒ w

hb∗

−−→ r2

I If the only path from write to read follows all this arrows, thenwe must not see earlier writes

I If multiple paths exist, you need to go deeperI We use hb∗ notation to distinguish it from hb and since "thishappens-before ordering does not transitively close with otherhappens-before orderings"

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

Page 37: Final field semantics

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

Field

Freezes of a final field occur both at the end of the constructor, andimmediately after each modification

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

Page 38: Final field semantics

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

Freeze action

Field

Freezes of a final field occur both at the end of the constructor, andimmediately after each modification

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

Page 39: Final field semantics

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

Freeze actionField

Freezes of a final field occur both at the end of the constructor, andimmediately after each modification39 / 104 (c) Copyright 2014, NetCracker Technology Corp. All rights reserved

Page 40: Final field semantics

Dereference chain: what is that? w hb−→ f hb−→ a mc−→ r1 dr−→ r2

T local = GLOBAL; r1

int localX = local.x; r2

I r2 reads a field of an object

I Current thread did not create the objectI Hence, we must read an address of the object somewhere

I This is called r1dr−→ r2

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

Page 41: Final field semantics

Dereference chain: what is that? w hb−→ f hb−→ a mc−→ r1 dr−→ r2

T local = GLOBAL; r1

int localX = local.x; r2

I r2 reads a field of an objectI Current thread did not create the object

I Hence, we must read an address of the object somewhere

I This is called r1dr−→ r2

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

Page 42: Final field semantics

Dereference chain: what is that? w hb−→ f hb−→ a mc−→ r1 dr−→ r2

T local = GLOBAL; r1

int localX = local.x; r2

I r2 reads a field of an objectI Current thread did not create the objectI Hence, we must read an address of the object somewhere

I This is called r1dr−→ r2

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

Page 43: Final field semantics

Dereference chain: what is that? w hb−→ f hb−→ a mc−→ r1 dr−→ r2

T local = GLOBAL; r1

int localX = local.x; r2

dr

I r2 reads a field of an objectI Current thread did not create the objectI Hence, we must read an address of the object somewhere

I This is called r1dr−→ r2

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

Page 44: Final field semantics

Dereference chain in two threads 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 (thread 2 reads a field of object created in a foreign thread)

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

Page 45: Final field semantics

Dereference chain in two threads 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?

Is there adr−→ r2?

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

Page 46: Final field semantics

Dereference chain in two threads 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 does not appear between actions of different threads!

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

Page 47: Final field semantics

Dereference chain: double-check w hb−→ f hb−→ a mc−→ r1 dr−→ r2

T local = GLOBAL; ra

local = GLOBAL; rb

int localX = local.x; r2

Is there a dr ?

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

Page 48: Final field semantics

Dereference chain: double-check w hb−→ f hb−→ a mc−→ r1 dr−→ r2

T local = GLOBAL; ra

local = GLOBAL; rb

int localX = local.x; r2

dr?

dr?

One of radr−→ r2 or rb

dr−→ r2 must exist, however no one can tell

which one48 / 104 (c) Copyright 2014, NetCracker Technology Corp. All rights reserved

Page 49: Final field semantics

Memory chain: what is that? 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

If a read sees write, then w1mc−−→ r1

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

Page 50: Final field semantics

Memory chain: what is that? 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

If a thread writes the address of an object that was initialized in

another thread, then r1mc−−→ w2

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

Page 51: Final field semantics

Memory chain: what is that? 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 sees w2 ⇒ w2mc−−→ r3

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

Page 52: Final field semantics

Memory chain: what is that? 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 (read of a object’s field)

⇒ r3mc−−→ r4

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

Page 53: Final field semantics

Memory chain: what is that? 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 (read of a object’s field) ⇒ r3

mc−−→ r4

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

Page 54: Final field semantics

Memory chain: what is that? 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 is transitive (it is a partial order) ⇒ w1mc−−→ r4

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

Page 55: Final field semantics

Introduction

Examples

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

Page 56: Final field semantics

Disclaimer

I All the examples contain data races (why bother otherwise?)

I We do not consider cases when null is observed (those cases arenot interesting)

I Lots of brains were hurt when preparing the slides

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

Page 57: Final field semantics

Disclaimer

I All the examples contain data races (why bother otherwise?)I We do not consider cases when null is observed (those cases arenot interesting)

I Lots of brains were hurt when preparing the slides

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

Page 58: Final field semantics

Disclaimer

I All the examples contain data races (why bother otherwise?)I We do not consider cases when null is observed (those cases arenot interesting)

I Lots of brains were hurt when preparing the slides

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

Page 59: Final field semantics

Trivial 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

}

Can result become 0?

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

Page 60: Final field semantics

Trivial 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

Actions in a thread form happens-before:

whb−−→ f , f

hb−−→ a

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

Page 61: Final field semantics

Trivial 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 sees write a :

amc−−→ r0

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

Page 62: Final field semantics

Trivial 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

Thread 2 did not create the object, r1 reads its field, and r is theonly read of the address, thus we have dereference chain:

r0dr−→ r1

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

Page 63: Final field semantics

Trivial 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

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

Page 64: Final field semantics

Trivial 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 is transitive)

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

Page 65: Final field semantics

Trivial 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

Let’s pick r2 = r1, then r1dr−→ r2 ( dr is reflexive)

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

Page 66: Final field semantics

Trivial 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*

Here all the requirements for HB∗:

whb−−→ f

hb−−→ a

mc−−→ r1

dr−→ r2⇒ w

hb∗

−−→ r2

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

Page 67: Final field semantics

Trivial 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}

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

Page 68: Final field semantics

Array in a final field (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

}

Can result become 0?

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

Page 69: Final field semantics

Array in a final field (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

Actions in a thread form happens-before:

whb−−→ f , f

hb−−→ a

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

Page 70: Final field semantics

Array in a final field (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 sees write a (it reads a regular final field):

amc−−→ r1

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

Page 71: Final field semantics

Array in a final field (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

Thread 2 did not create array, r2 reads an element of the array, r1 isthe only read of the address of the array, thus dereference chain:

r1dr−→ r2

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

Page 72: Final field semantics

Array in a final field (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*

Here are all the requirements for HB∗:

whb−−→ f

hb−−→ a

mc−−→ r1

dr−→ r2⇒ w

hb∗

−−→ r2

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

Page 73: Final field semantics

Array in a final field (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}

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

Page 74: Final field semantics

Array reversed (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];

}

Can result become 0?

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

Page 75: Final field semantics

Array reversed (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∗

We compose hb∗ exactly as in the previous example

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

Page 76: Final field semantics

Array reversed (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}The result does not depend on the order of assignment to final fields!

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

Page 77: Final field semantics

this leaks (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

}

Can result become 0?

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

Page 78: Final field semantics

this leaks (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

Actions in thread form happens-before:

whb−−→ f , a

hb−−→ f

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

Page 79: Final field semantics

this leaks (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?

For hb∗ we need fhb−−→ a!

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

Page 80: Final field semantics

this leaks (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?

If ahb−−→ f and f

hb−−→ a, thus a = f (anti-symmetry of hb )

However a is cannot be a freeze action!

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

Page 81: Final field semantics

this leaks (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?

There is no hb∗ , thus all the cases are possible: result ∈ {0, 42}

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

Page 82: Final field semantics

Unintentional this leak (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

}

Can result become 0?

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

Page 83: Final field semantics

Unintentional this leak (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?

Actions in a thread form happens-before:

whb−−→ f , f

hb−−→ a

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

Page 84: Final field semantics

Unintentional this leak (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

Suppose thread 2 sees GLa, thus amc−−→ ra!

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

Page 85: Final field semantics

Unintentional this leak (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?

There should be dr somewhere: rbdr−→ r1 or ra

dr−→ r1

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

Page 86: Final field semantics

Unintentional this leak (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

If rbdr−→ r1, then we fail, since w

hb∗

−−→ r1 can not be completed

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

Page 87: Final field semantics

Unintentional this leak (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

Conclusion: if a thread had ever seen object with unfrozen fields,then there is no final semantics for that object!

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

Page 88: Final field semantics

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

}

Can result become 0?88 / 104 (c) Copyright 2014, NetCracker Technology Corp. All rights reserved

Page 89: Final field semantics

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*?

We’d better have w2hb∗

−−→ r2 (otherwise we must not see the writeof 0 in w.x)

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

Page 90: Final field semantics

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 does not work for hb∗ : there is no suitable f 2hb−−→ a

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

Page 91: Final field semantics

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 does not work for hb∗ as well: it must be w2hb−−→ f 1

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

Page 92: Final field semantics

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?

It turns out r2 is not denied to observe 0

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

Page 93: Final field semantics

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?

Conclusion: do not alter the final field after you publish its contentsresult ∈ {0, 1, 42}

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

Page 94: Final field semantics

Let’s fix 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;

}

If we publish the object after all modifications of final fields, thepublication is safe: result ∈ {1, 42}

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

Page 95: Final field semantics

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

Can result become 0?

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

Page 96: Final field semantics

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 sees wb ⇒ wbmc−−→ rb

ra sees wa : wamc−−→ ra

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

Page 97: Final field semantics

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

Thread 2 writes an address of a foreign-created object, thus

ramc−−→ wb

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

Page 98: Final field semantics

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

Therad 3 did not create object A, r reads its field, and rb is theonly read of A’s address, thus dereference chain:

rbdr−→ r1

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

Page 99: Final field semantics

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

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

Page 100: Final field semantics

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 is transitive (since it is a partial order) ⇒ wamc−−→ r1

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

Page 101: Final field semantics

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

Let’s pick r2 = r1, thus r1dr−→ r2 ( dr is reflexive)

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

Page 102: Final field semantics

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*

Here are all the requirements for HB∗:

whb−−→ f

hb−−→ a

mc−−→ r1

dr−→ r2⇒ w

hb∗

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

Page 103: Final field semantics

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}

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

Page 104: Final field semantics

Questions?

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


Top Related