Java Reference
In-Depth Information
static void reader() {
if (f != null) {
int i = f.x; // guaranteed to see 3
int j = f.y; // could see 0
}
}
}
The class
FinalFieldExample
has a
final int
field
x
and a non-
final int
field
y
. One thread
might execute the method
writer
and another might execute the method
reader
.
Because the
writer
method writes
f
after
the object's constructor finishes, the
reader
method will be guaranteed to see the properly initialized value for
f.x
: it will read the
value
3
. However,
f.y
is not
final
; the
reader
method is therefore not guaranteed to see
the value
4
for it.
Example 17.5-2.
final
Fields For Security
final
fields are designed to allow for necessary security guarantees. Consider the fol-
lowing program. One thread (which we shall refer to as thread 1) executes:
Global.s = "/tmp/usr".substring(4);
while another thread (thread 2) executes
String myS = Global.s;
if (myS.equals("/tmp"))System.out.println(myS);
String
objects are intended to be immutable and string operations do not perform syn-
chronization. While the
String
implementation does not have any data races, other code
could have data races involving the use of
String
objects, and the memory model makes
weak guarantees for programs that have data races. In particular, if the fields of the
String
class were not
final
, then it would be possible (although unlikely) that thread 2
could initially see the default value of
0
for the offset of the string object, allowing it
to compare as equal to “
/tmp
”. A later operation on the
String
object might see the cor-
rect offset of
4
, so that the
String
object is perceived as being “
/usr
”. Many security fea-
tures of the Java programming language depend upon
String
objects being perceived
as truly immutable, even if malicious code is using data races to pass
String
references
between threads.