Immutability offers several benefits, such as thread-safety and prevention of inadvertent modification of fields and malicious tampering. Class invariants and state of immutable objects are always consistent with their requirements, so of fields prevents inadvertent modification as well as malicious tampering so that defensive copying while accepting input or returning values is unnecessary. However, it is sometimes impossible to make some sensitive classes cannot be immutable. Fortunately, a mechanism exists that allows code to expose mutable classes to untrusted code by granting read-only access, which is achieved largely through read-only access to mutable classes can be granted to untrusted code using unmodifiable wrappers. For example, the Collection
classes include a set of wrappers that allow clients to observe an unmodifiable view of a Collection
object.
...
An untrusted invoker may call the mutator method setArray()
, and violate the object's immutability property. Invoking the getter method getArray()
also allows modification of the private internal state of the class. This class also violates OBJ05-J. Defensively copy private mutable class members before returning their references.
...
This noncompliant code example subclasses extends the Mutable
class with a MutableProtector
subclass:
Code Block | ||||
---|---|---|---|---|
| ||||
class MutableProtector extends Mutable { @Override public int[] getArray() { return super.getArray().clone(); } } // ... private Mutable mutable = new MutableProtector(); public Mutable getMutable() {return mutable;} // May be safely invoked by untrusted caller having read ability |
In this class, invoking the getter method getArray()
does not allow modification of the private internal state of the class, in accordance with OBJ05-J. Defensively copy private mutable class members before returning their references. However, an untrusted invoker may call the method setArray()
and modify the Mutable
object.
...
Code Block | ||||
---|---|---|---|---|
| ||||
class MutableProtector extends Mutable {
@Override
public int[] getArray() {
return super.getArray().clone();
}
@Override
public void setArray(int[] i) {
throw new UnsupportedOperationException();
}
}
// ...
private Mutable mutable = new MutableProtector();
public Mutable getMutable() {return mutable;} // May be safely invoked by untrusted caller having read ability
|
The MutableProtector
wrapper class overrides the getArray()
method and clones the array. Although the calling code gets a copy of the mutable object's array, the original array remains unchanged and inaccessible. The overriding setArray()
method throws an exception if the caller attempts to use this method on the returned object. This object can be passed to untrusted code when read-access to the data is permissible.
...