230 likes | 245 Vues
Object and Reference Immutability using Java Generics. Yoav Zibin(1), Alex Potanin(2), Shay Artzi(1), Adam Kiezun(1), and Michael D. Ernst(1) 1) MIT Computer Science and Artificial Intelligence Lab, USA 2) Victoria University of Wellington, New-Zealand
E N D
Object and Reference Immutability using Java Generics Yoav Zibin(1), Alex Potanin(2), Shay Artzi(1), Adam Kiezun(1), and Michael D. Ernst(1) 1) MIT Computer Science and Artificial Intelligence Lab, USA 2) Victoria University of Wellington, New-Zealand Presenting: Ori Arad (sorry@t2.technion.ac.il) – 14/2/07
Program comprehension Verification Compile & Run-time optimizations Invariant detection Refactoring Test input generation Regression oracle creation Specification mining Modeling Immutability – What for?...
Immutability varieties • Class immutability • No instance of an immutable class may be change after creation (e.g. String, Integer etc.) • Object immutability • Immutable instances may not be changed, while other instances (of the same class) may… • Reference immutability • a given reference cannot be used to modify its referent.
IGJ - Immutability Generic Java • Object immutability: • An object: mutable or immutable. • Reference immutability: • A reference: Immutable, Mutable, or ReadOnly • Class immutability • Also support Class immutability
IGJ - Immutability Generic Java 1: // An immutable reference to an immutable date; side effects are prohibited 2: Date<Immutable> immutD = new Date<Immutable>(); 3: // A mutable reference to a mutable date; side effects are permitted 4: Date<Mutable> mutD = new Date<Mutable>(); 5: // A readonly reference to any date; side effects are prohibited 6: Date<ReadOnly> roD = ... ? immutD : mutD; one new generic parameter (at the beginning of the list of generic parameters) was added
IGJ main design principles • Transitivity: The design must provide transitive (deep) immutability • Purely static: There should be no runtime representation for immutability • Polymorphism: It must be possible to abstract over immutability without code duplication • Simplicity: The design should not change Java's syntax and have a small set of typing rules
Type Hierarchies for IGJ The type hierarchy for immutability parameters The top of the type hierarchy for all other classes
IGJ Subtype hierarchy Legend: L List, O object, R ReadOnly IM Immutable, M Mutable For example: L< R,O<M> > means List<ReadOnly, Object<Mutable>> // Demonstrates how to copy value of readonly roObj to mutable mutableObj Object<ReadOnly> roObj = ...; List<Mutable,Object<Mutable>> l = new List<Mutable,Object<Mutable>>(); ((List<Mutable,Object<ReadOnly>>) l).add(roObj); Object<Mutable> mutableObj = l.get(0); // mutableObj equals roObj
Java Array Co-Variance Problem // A is a single-element array of String. String[] a = new String[1]; // B is an array of Object Object[] b = a; // Assign an Integer to b. This would be possible if b really were // an array of Object, but since it really is an array of String, // we will get a java.lang.ArrayStoreException. b[0] = new Integer (1); Read from Array: OK! Write to Array: Problem! Solution with IGJ – immutability promise us only reading no Co-Variance problem
The Field Rule Typing is guaranteed by several rules. Let I(x) denote the immutability of x Rule I: Field Assignment Rule legal iff I(o) = Mutable. Example: o.someField = exp; Employee<ReadOnly> roE = ...; roE.address = ...; // Compilation error!
"Immutability" of Methods • 4 new annotations: @ReadOnly, @Mutable, @Immutable and @AssignFields • Example: @Mutable void m() {...this...} • Here: I(this) is Mutable • In general: in any method m, I(this) is the same as I(m) • “this” immutability depends on the context
Reference-Immutability Rules • Method Invocation Rule: • (not necessarily I(o) = I(m) ) o.m(...) is legal if I(o) is subtype of I(m). Employee<Mutable> o = ...; o.setAddress(...); // OK since I(o) = Mutable and I(setAddress) = Mutable o.getAddress(); // OK since I(o) = Mutable and I(getAddress) = ReadOnly ((Employee<ReadOnly>) o).setAddress(...); // Compilation error!
ExampleIGJ classes Edge<I> and Graph<I>, with the immutability parameters (and annotations, for this) underlined. 1: class Edge<I extends ReadOnly> { 2: privatelong id; 3: public @AssignFields Edge(long id) { this.setId(id); } 4: public @AssignFields synchronized void setId(long id) { 5: this.id = id; } 6: public @ReadOnly synchronized long getId() { return id; } 7: public @Immutable long getIdImmutable() { return id; } 8: publicstatic void print(Edge<ReadOnly> n) {... } 9: } 10: class Graph<I extends ReadOnly> { 11: public Edge<I> lastN; 12: public List<I,Edge<I>> l; 13: public @AssignFields Graph(List<I,Edge<I>> l) { this.l = l; } 14: public @Mutable void addEdge(Edge<I> n) { 15: this.l.add(n); this.lastN = n; } 16: public @ReadOnly Edge<I> getLast() { return this.lastN; } 17: publicstatic <T extends ReadOnly> 18: Edge<T> findEdge(Graph<T> nl, long id) { ... } 19: } For now: Assume @Immutable is like @ReadOnly And @AssignFields is like @Mutable
Example: 1: class Edge<I extends ReadOnly> { 2: private long id; 3: public @AssignFields Edge(long id) { this.setId(id); } 4: public @AssignFields synchronized void setId(long id) { 5: this.id = id; } 6: public @ReadOnly synchronizedlong getId() { return id; } 7: public @Immutable long getIdImmutable() { return id; } 8: publicstatic void print(Edge<ReadOnly> n) {... } 9: } • Line 5: the assignment into this.id is OK • If this.id = …; was on line 6 – illegal… • Line 3: OK due to Method Rule • Line 8: static no annotation, Edge of any immutability could be pass here…
Example: 10: class Graph<I extends ReadOnly> { 11: public Edge<I> lastN; 12: public List<I,Edge<I>> l; 13: public @AssignFields Graph(List<I,Edge<I>> l) { this.l = l; } 14: public @Mutable void addEdge(Edge<I> n) { 15: this.l.add(n); this.lastN = n; } 16: public @ReadOnly Edge<I> getLast() { returnthis.lastN; } 17: publicstatic <T extends ReadOnly> 18: Edge<T> findEdge(Graph<T> nl, long id) { ... } 19: } • Line 11: a class can pass its immutability parameter to its fields • Line 16: Also return type – no need for overloading • Line 12: Transitivity - in an immutable Graph the field l will contain an immutable list of immutable edges
Object Immutability & constructors • What annotation should CTOR be?... • @Mutable? problem: public @Mutable Graph(List<I,Edge<I>> l) { this.l = l; this.addEdge( new Edge<Mutable>(0) ); // } … List<Immutable,Edge<Immutable>> imList = ...; new Graph<Immutable>(imList); // An element was added to imList • @Immutable? Guess not…
Object Immutability & constructors • Solution: Forth kind of reference immutability: AssignFields • Permit to perform limited side-effects without permitting modification of immutable objects • @Mutable method can assign & mutate • @AssignFields method can only assign
Immutability & Assignability • MyClass myObject = new MyClass(); • myObject = anotherObject; • Assignability • myObject.setField(4); • immutability
Revised rules • Field Rule revised (relaxed): • AssignField is not transitive… • Method Rule revised (restricted): o.someField = ...; is legal if I(o) = Mutableor (I(o) = AssignFields and o=this) o.m(...) is legal if I(o) is subtype of I(m)and (I(m) = AssignFields implies o=this)
Example: 1: class Edge<I extends ReadOnly> { 2: privatelong id; 3: public @AssignFields Edge(long id) { this.setId(id); } 4: public @AssignFields synchronized void setId(long id) { 5: this.id = id; } 6: public @ReadOnly synchronized long getId() { return id;} 7: public @Immutable long getIdImmutable() { return id; } 8: publicstatic void print(Edge<ReadOnly> n) {... } 9: } • Line 5: the assignment into this.id is still OK setId is annotated with @AssignFields I(this)=AssignFields • Line 3: I(this) = AssignFields & I(setId) = AssignFields
Example: public @mutable Graph(List<I,Edge<I>> l) { this.l = l; this.l.get(0).setId(42); // } • Line 13: If we will add the following code – it will be illegal in the revised rule (and legal in the old one) • New Rule:new SomeClass<X,…>(…) is legal only if • X = Mutable and this CTOR is not marked as @Mutable, or • X = Imuutable and this CTOR is not marked as @Immutable • (X = readOnly & X=AssignFileds are illegal)
Future Work • Plug-in for IDE (e.g. Eclipse) • A WriteOnly immutability parameter • @readable notation for field class Vector<I extends None, T> { @readable int size; ... @None int size() { return size; } @WriteOnly void add(T t) { ... } @WriteOnly void removeLast() { ... } @Mutable void remove(T t) { ... } @ReadOnly void get(int index) { ... } }
Future Work (cont.) • Add default immutability class Graph<I extends ReadOnly default Mutable> • An alternative syntax (Java 7?...) @immutable Document[@readonly] new @mutable ArrayList<@immutable Edge>(...) • Runtime support (e.g. down-cast)