According to JSR-133 immutable objects are thread safe and don't need synchronization. However it's possible to update values of final fields using reflection:
package com.stackoverflow;
import java.lang.reflect.Field;
public class WhatsGoingOn {
static class Immutable {
private final int value;
public Immutable(int value) {
this.value = value;
}
public int getValue() {
return value;
}
}
public static void main(String[] args) throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException {
final Immutable immutable = new Immutable(Integer.MIN_VALUE);
final Field f = Immutable.class.getDeclaredField("value");
f.setAccessible(true);
System.out.println(immutable.getValue());
f.set(immutable, Integer.MAX_VALUE);
System.out.println(immutable.getValue());
}
}
Given number of frameworks (Spring and Hibernate are only a few) which rely on reflection I'm curious what does spec says about this scenario. E.g. if I put field update into synchronized block will that guarantee visibility in other threads, or value will be cached in registers as per spec for final.
http://download.oracle.com/otndocs/jcp/memory_model-1.0-pfd-spec-oth-JSpec/
Immutable objects offer a number of advantages for building reliable applications. As we don't need to write defensive or protective code to keep application state consistent, our code can be simpler, more concise, and less error-prone than when we define mutable objects.
Immutability is the idea that data or objects should not be modified after they are created. This concept has permeated throughout computing, and it is a core tenant of functional programming languages such as Haskell, Erlang, and Clojure.
An immutable object (unchangeable object) is an object whose state cannot be modified after it is created. This is in contrast to a mutable object (changeable object), which can be modified after it is created.
An object is considered immutable if its state cannot change after it is constructed. http://docs.oracle.com/javase/tutorial/essential/concurrency/immutable.html
You are using that Object as mutable since you are changing its state.
It is true that the use of Reflection breaks immutability as defined in the tutorial, since you can use it to change non-constant final fields.
An example of a Reflection-resistant immutable object would be the following:
static class Immutable {
// This field is a constant, and cannot be changed using Reflection
private final int value = Integer.MIN_VALUE;
public int getValue() {
return value;
}
}
public static void main(String[] args) throws NoSuchFieldException, SecurityException, IllegalArgumentException, IllegalAccessException {
final Immutable immutable = new Immutable();
final Field f = Immutable.class.getDeclaredField("value");
f.setAccessible(true);
System.out.println(immutable.getValue());
f.set(immutable, Integer.MAX_VALUE);
System.out.println(immutable.getValue());
}
In this instance your reflection test will fail, and the value will remain Integer.MIN_VALUE
. But hey, we could always use native code or a memory editor to change that value to something else.
If you go this far into hacking with reflection, you might as well not call your field final and provide methods for manipulating it.
All bets are off with reflection if you insist on switching access control off and doing naughty things.
Static constants are usually inlined at compile time so changing their value probably would have no impact anyway. The result really depends on how clever the optimiser is when compiling, and how clever the JIT compiler is at run time.
End result: "Here be dragons, fear all who dare to tread here!"
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With