final field semantics

Post on 24-Jun-2015

1.063 Views

Category:

Documents

0 Downloads

Preview:

Click to see full reader

DESCRIPTION

Final keyword in java is known to forbid class extension and modification of the fields. It is less known to have special meaning in multithreaded code. Unfortunately, there is not that much information on the latter, and even most thorough talks avoid deep details on the beauty of finals. In this talk I apply section 17.5 of java language specification to different examples and show how the spec works. Several myths are busted on the way. Here's nice article on different aspects of JMM: http://shipilev.net/blog/2014/jmm-pragmatics/

TRANSCRIPT

Semantics of final fields in java

Vladimir Sitnikov, Valentin Kovalenkositnikov@netcracker.com, @VladimirSitnikv

NetCracker

September 2014

Introduction

Examples

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

Why final is required inJMM?

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

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

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

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

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

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

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

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

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

Зачем нам JMM?

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

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

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

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

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

A bit of theory

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Introduction

Examples

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Questions?

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

top related