Javari: Adding Reference Immutability to Java Rauno Ots Matthew S. Tschantz Michael D. Ernst MIT...

48
Javari: Adding Reference Immutability to Java Rauno Ots Matthew S. Tschantz Michael D. Ernst MIT CSAIL 2005

Transcript of Javari: Adding Reference Immutability to Java Rauno Ots Matthew S. Tschantz Michael D. Ernst MIT...

Page 1: Javari: Adding Reference Immutability to Java Rauno Ots Matthew S. Tschantz Michael D. Ernst MIT CSAIL 2005.

Javari: Adding Reference Immutability to Java

Rauno Ots

Matthew S. TschantzMichael D. ErnstMIT CSAIL 2005

Page 2: Javari: Adding Reference Immutability to Java Rauno Ots Matthew S. Tschantz Michael D. Ernst MIT CSAIL 2005.

Intro

1. Immutability2. Motivation3. Javari4. Formalization5. Some problems

o Templetizingo Annotations

– Checker framework

Page 3: Javari: Adding Reference Immutability to Java Rauno Ots Matthew S. Tschantz Michael D. Ernst MIT CSAIL 2005.

Immutability

An object is immutable (readonly) if it is not allowed to be changed, mutated.

The abstract state of an object must remain unchanged. This includes the abstract state of objects referenced from it.

Object immutability or reference immutability.

Reference immutability - readonly reference cannot be used to modify the object or its transitive state.• other references to the same object still may change it

Page 4: Javari: Adding Reference Immutability to Java Rauno Ots Matthew S. Tschantz Michael D. Ernst MIT CSAIL 2005.

Type system with reference immutability• increase expressiveness, enhance program understanding• compiler-enforced guarantees• provide machine-checked documentation• prevent and detect errors• enable analyses and transformations that depend

on compiler-verified properties

Page 5: Javari: Adding Reference Immutability to Java Rauno Ots Matthew S. Tschantz Michael D. Ernst MIT CSAIL 2005.

Motivation - Example 1

ElectionResults tabulate(Ballots votes) { ... } vs

ElectionResults tabulate(readonly Ballots votes) {   ... // cannot tamper with the votes}

Page 6: Javari: Adding Reference Immutability to Java Rauno Ots Matthew S. Tschantz Michael D. Ernst MIT CSAIL 2005.

Motivation - Example 2

      class FileSystem {          private List<Inode> inodes;          List<Inode> getInodes() {              ... // Unrealistic to copy          }      }

vs       class FileSystem {          private List<Inode> inodes;          readonly List<readonly Inode> getInodes(){               ...           }      }

Page 7: Javari: Adding Reference Immutability to Java Rauno Ots Matthew S. Tschantz Michael D. Ernst MIT CSAIL 2005.

Motivation - Example 3

some data structures must be treated as mutable when they are being initialized, but as immutable thereafter

      Graph g1 = new Graph();      ... construct cyclic graph g1 ...      // Suppose no aliases to g1 exist.      readonly Graph g = g1;      g1 = null;

Page 8: Javari: Adding Reference Immutability to Java Rauno Ots Matthew S. Tschantz Michael D. Ernst MIT CSAIL 2005.

Javari

1. Assignability2. Mutability3. Fields: this-assignable and this-mutable4. Generics5. Arrays6. Summary

Page 9: Javari: Adding Reference Immutability to Java Rauno Ots Matthew S. Tschantz Michael D. Ernst MIT CSAIL 2005.

Assignability

• whether a reference may be reassigned• by default, assignable• Java's final keyword makes a variable unassignable• Javari adds assignable keyword to provide greater

control

final Date d = new Date(); // unassignable      Date e = new Date(); // assignable      e = d; //OK      d = e; //error: d cannot be reassigned

Page 10: Javari: Adding Reference Immutability to Java Rauno Ots Matthew S. Tschantz Michael D. Ernst MIT CSAIL 2005.

Mutability

• Mutation is any modification to an object’s abstract state• The abstract state is (part of) the transitively

reachable state, which is the state of the object and all states reachable from it by following references

• By default, mutable, all primitives, immutable• Keywords readonly and mutable to control

readonly Date rodate; // readonly reference to a Date object...   rodate.getMonth();    // OKrodate.setYear(2005); // error

Page 11: Javari: Adding Reference Immutability to Java Rauno Ots Matthew S. Tschantz Michael D. Ernst MIT CSAIL 2005.

Mutability II

• For every Java reference type T, readonly T is a valid Javari type and a supertype of T

• mutable reference can be used, where read-only is expected

• read-only reference is missing some functionality• readonly can be thought of as an interface

readonly Date rodate = new Date(); /*mutable*/ Date date = new Date();      rodate = date;    // OKrodate = (readonly Date) date; // OKdate = rodate;    // errordate = (Date) rodate; // error: Java cast cannot make a readonly reference mutable

Page 12: Javari: Adding Reference Immutability to Java Rauno Ots Matthew S. Tschantz Michael D. Ernst MIT CSAIL 2005.

Mutability III

• readonly can be used in a declaration of any local variable, field, parameter or method return type

• by default, mutableo except fieldso primitives always immutable

Note: assignability (final and assignable) and mutability (readonly and mutable) are independend properties of a variable.• final variable may still be mutated• readonly makes referenced object non-mutable, but the

variable may remain assignable 

Page 13: Javari: Adding Reference Immutability to Java Rauno Ots Matthew S. Tschantz Michael D. Ernst MIT CSAIL 2005.

Mutability: Read-only methods

•  readonly can be applied to any explicit formal parameter of a method

• also, can be applied to the implicit this parameter• non-readonly method cannot be called through a read-only

reference

      class StringBuffer{            ...            public char charAt(int index) readonly {                 ... // this is readonly            }      }

Page 14: Javari: Adding Reference Immutability to Java Rauno Ots Matthew S. Tschantz Michael D. Ernst MIT CSAIL 2005.

Mutability: Overloading

• Identical to Java (except the mutability of receiver)• Performed in two steps

1.Compile-time (overloaded)1.Finds most specific signature2.No matching signatures or no single most specific

match issues a compile-time error2.Runtime - dynamic dispatch (overridden)

 previously matched signature is selected  implementation whose receiver is greatest, but at most

the runtime type of the receiver object  

void bar(readonly Date) { ... }void bar(/*mutable*/ Date) { ... } // overloaded

Page 15: Javari: Adding Reference Immutability to Java Rauno Ots Matthew S. Tschantz Michael D. Ernst MIT CSAIL 2005.

Mutability: Overloading mutability of receiver• a read-only method overloads (not overrides) a non-read-

only method of same name and parameters• dynamic dispatch does not work

1.no implementation, only compile-time checks• either holes in type system, or limits to method actions

      class Foo {            void bar() readonly  { System.out.println(0); }                 // overloads, not overrides, bar() readonly:            void bar() /*mutable*/ { System.out.println(1); }      }

            /*mutable*/ Foo f = new Foo();       readonly Foo rf = f;                        rf.bar();  // Prints 0              f.bar();   // Prints 1

Page 16: Javari: Adding Reference Immutability to Java Rauno Ots Matthew S. Tschantz Michael D. Ernst MIT CSAIL 2005.

Mutability: Immutable classes

• Class or interface can be declared readonlyo class’s non-static fields default to read-only and final, and

its non-static methods (and, for inner classes, constructors) default to read-only

o every reference to an object of immutable type T is implicitly read-only

o Subclasses or subinterfaces of immutable classes and interfaces must be immutable

    readonly class String { ... }    /*readonly*/ String s1 = new String();    readonly String s2 = new String();    s1 = s2;    // OK    s2 = s1;    // OK

Page 17: Javari: Adding Reference Immutability to Java Rauno Ots Matthew S. Tschantz Michael D. Ernst MIT CSAIL 2005.

Fields: this-assignable and this-mutable

• By default field inherits from accessed referenceo if accessed through read-only reference

then unassignable and read-onlyo if accessed through mutable reference

then assignable and mutable

These defaults are called this-assignability and this-mutability.

Can be overriden using keywords:final or assignable, readonly or mutableto exclude specific fields from the object’s abstract state.

Page 18: Javari: Adding Reference Immutability to Java Rauno Ots Matthew S. Tschantz Michael D. Ernst MIT CSAIL 2005.

Fields: this-assignable and this-mutable - example

   class Cell {     /*this-assignable this-mutable*/ Date d;   }            

   /*mutable*/ Cell c;     // mutable   readonly Cell rc;       // read-only               c.d = new Date();       // OK: c.d is assignable              rc.d = new Date();      // error: rc.d is unassignable (final)               /*mutable*/ Date d1 = c.d;   // OK: c.d is mutable   /*mutable*/ Date d2 = rc.d;  // error: rc.d is read-only               c.d.setYear(2005);      // OK: c.d is mutable   rc.d.setYear(2005);     // error: rc.d is read-only

Page 19: Javari: Adding Reference Immutability to Java Rauno Ots Matthew S. Tschantz Michael D. Ernst MIT CSAIL 2005.

Field accesses within methods

class Cell {      /*this-assignable this-mutable*/ Date d;            /*mutable*/ Date foo() readonly {// this is readonly           d = new Date(); // error: this.d is unassignable           d.setYear(2005);// error: this.d is readonly           return d;       // error: this.d is readonly                 }           /*mutable*/ Date bar() /*mutable*/ {// this is mutable           d = new Date();  // OK: this.d is assignable           d.setYear(2005); // OK: this.d is mutable           return d;        // OK: this.d is mutable      }}

Page 20: Javari: Adding Reference Immutability to Java Rauno Ots Matthew S. Tschantz Michael D. Ernst MIT CSAIL 2005.

Assignable fields

• Can be used for caching

         class Foo {            assignable int hc;            int hashCode() readonly {                  if (hc == 0) {                        // OK: hc is assignable                        hc = ... ;                  }                  return hc;            }      }

Page 21: Javari: Adding Reference Immutability to Java Rauno Ots Matthew S. Tschantz Michael D. Ernst MIT CSAIL 2005.

Assignable fields (Loophole)

/** Assignable Cell. */class ACell {      assignable /*this-mutable*/ Date d;} /** Converts a read-only Date to a mutable date. */static /*mutable*/ Date convertReadonlyToMutable(readonly Date roDate) {      /*mutable*/ ACell mutCell = new ACell();      readonly ACell roCell = mutCell;            roCell.d = roDate;    // assign a readonly reference      /*mutable*/ Date mutDate = mutCell.d;      return mutDate;}

Page 22: Javari: Adding Reference Immutability to Java Rauno Ots Matthew S. Tschantz Michael D. Ernst MIT CSAIL 2005.

Assignable fields (Loophole solution)

Even if used through readonly reference, the this-mutable field is potentially mutable

Can assign only mutable references

Page 23: Javari: Adding Reference Immutability to Java Rauno Ots Matthew S. Tschantz Michael D. Ernst MIT CSAIL 2005.

Mutable fields

• Mutable, even if referenced through a read-only reference• Field's value is not a part of the abstract state of te object,

but the field's identity may be

class Foo {      final mutable List<String> log;      int hashCode() readonly {            // OK: log is mutable            log.add("entered hashCode()");            ...      }}

Page 24: Javari: Adding Reference Immutability to Java Rauno Ots Matthew S. Tschantz Michael D. Ernst MIT CSAIL 2005.

Generic classes

/*mutable*/ List</*mutable*/ Date>  ld1; // add/rem./mut./*mutable*/ List<readonly Date>     ld2; // add/removereadonly List</*mutable*/Date>     ld3;  // mutatereadonly List<readonly Date> ld4;        // (neither)

class DateList {      // 3 readonly lists whose elements have different mutability      readonly List</*this-mutable*/Date> lst;      readonly List<readonly Date> lst2;      readonly List<mutable Date> lst3;}

Page 25: Javari: Adding Reference Immutability to Java Rauno Ots Matthew S. Tschantz Michael D. Ernst MIT CSAIL 2005.

Generic classes II

class Foo<T extends readonly Object> {    // a is not this-mutable. Its mutability is determined    // solely by the type that T is instantiated with.    T a; // OK    readonly T b; // OK: can only result in upcasts    mutable T c; // error: T can be instantiated with a    // read-only type that cannot be    // casted to a mutable type.    this-mutable T d; // error: and not valid syntax}

new Foo</*mutable*/ Object>();new Foo<readonly Object>();

Page 26: Javari: Adding Reference Immutability to Java Rauno Ots Matthew S. Tschantz Michael D. Ernst MIT CSAIL 2005.

Arrays

Nothing special                   Date [] ad1;//add/remove, mutate         (readonly Date)[] ad2;//add/removereadonly           Date [] ad3;//mutatereadonly (readonly Date)[] ad4;//no add/rem., no mutate       (readonly Date[])[] ad5;//readonly inner array

To avoid a run-time representation of immutability, Javari does not allow covariance across the mutability of array element typesDate[] b=new Date[2];Object[] a=b;     //OKa[0]=new Object();//Runtime error

ad2 = ad1; //error

Page 27: Javari: Adding Reference Immutability to Java Rauno Ots Matthew S. Tschantz Michael D. Ernst MIT CSAIL 2005.

Javari keywords summary

• final - declares a reference to be unassignable.• assignable - declares a reference always to be

assignable even if accessed through a read-only reference. o Redundant for references other than instance fields.

• readonly - declares a reference to be read-only. o Redundant for immutable types.

• mutable - declares a reference always to be mutable even if accessed through a read-only reference. o Redundant for references other than instance fields.o Cannot be applied to type parameters

• romaybe - special keyword to avoid code duplication

Page 28: Javari: Adding Reference Immutability to Java Rauno Ots Matthew S. Tschantz Michael D. Ernst MIT CSAIL 2005.

Summary

Page 29: Javari: Adding Reference Immutability to Java Rauno Ots Matthew S. Tschantz Michael D. Ernst MIT CSAIL 2005.

Formalization

1. Featherweight Generic Java to Lightweight Javao field assignmento the final keyword

– Lightweight Java to Lightweight Javario reference immutability

Page 30: Javari: Adding Reference Immutability to Java Rauno Ots Matthew S. Tschantz Michael D. Ernst MIT CSAIL 2005.

Lightweight Java syntax

Page 31: Javari: Adding Reference Immutability to Java Rauno Ots Matthew S. Tschantz Michael D. Ernst MIT CSAIL 2005.

• No interfaces• No field shadowing or overloading• Single constructor in form

• The set construct to avoid the complications of allowing multiple expressions within a method

Lightweight Java

Page 32: Javari: Adding Reference Immutability to Java Rauno Ots Matthew S. Tschantz Michael D. Ernst MIT CSAIL 2005.

LJ syntax

S, T, U, V - typesX, Y, Z - type variablesN, P, Q - nonvariable typesC - unparametherized class namesf,g - field namesAF - assignability of fieldsK - constructor declarationM - method declaratione - expressionx - variable

Page 33: Javari: Adding Reference Immutability to Java Rauno Ots Matthew S. Tschantz Michael D. Ernst MIT CSAIL 2005.

LJ syntax• Γ  - mapping from variables to types. 

• fields(N) - sequence of triplets, AF T f

• bound ∆ (T) - the upper bound of T in type environment ∆: ∆(T) if T is a type parameter, or T if T is a nonvariable type.

• mtype(m, N) - the type of method m of the nonvariable type N.  as <X   ⊳ N>T → T where X, with the bounds N, are the type parameters of the method, T are the types of the method’s parameters, and T is the return type of the method.

• mbody(m<V>, N) - the pair x.e where x are the formal parameters to m in N and e is the body of the method.

• override(m, N, <Y   ⊳ P>T → T) - method m with type <Y   ⊳ P>T → T) correctly overrides any methods with the same name possessed by the nonvariable type N

• [a/b]c - replacing b by a in c.

• ∆ ⊣ T ok declares that type T is well formed under context ∆. A type is well formed if its type parameters respect the bounds placed on them in the class’s declaration.

• M OK IN C declares that method declaration M is sound in the context of class C. • C OK declares the class declaration of C to be sound.

Page 34: Javari: Adding Reference Immutability to Java Rauno Ots Matthew S. Tschantz Michael D. Ernst MIT CSAIL 2005.

Lightweight Java

Page 35: Javari: Adding Reference Immutability to Java Rauno Ots Matthew S. Tschantz Michael D. Ernst MIT CSAIL 2005.

LJ storing the fields

• To support the assignment of fields, we introduce a store S to the reduction rules.

• S is a mapping from an object to a pair containing the nonvariable type of the object and a field record.

• A field record F is a mapping from field names to values.

• Each reduction rule is a relationship, e, S → e' , S' , ⟨ ⟩ ⟨ ⟩where e with store S reduces to e' with store S' in one step.

Page 36: Javari: Adding Reference Immutability to Java Rauno Ots Matthew S. Tschantz Michael D. Ernst MIT CSAIL 2005.

Lightweight Java

Page 37: Javari: Adding Reference Immutability to Java Rauno Ots Matthew S. Tschantz Michael D. Ernst MIT CSAIL 2005.

Lightweight Javari

Page 38: Javari: Adding Reference Immutability to Java Rauno Ots Matthew S. Tschantz Michael D. Ernst MIT CSAIL 2005.

Lightweight Javari

• Every type is is modified by one of the mutability modifiers: readonly, mutable or (for fields) this-mutable.

• Addition of this-assignable keyword

Page 39: Javari: Adding Reference Immutability to Java Rauno Ots Matthew S. Tschantz Michael D. Ernst MIT CSAIL 2005.

Lightweight Javari

Page 40: Javari: Adding Reference Immutability to Java Rauno Ots Matthew S. Tschantz Michael D. Ernst MIT CSAIL 2005.

Lightweight Javari

Page 41: Javari: Adding Reference Immutability to Java Rauno Ots Matthew S. Tschantz Michael D. Ernst MIT CSAIL 2005.

Templatizing methods over mutabilityto avoid code duplication• In Javari, definition class C{ .. } creates two types: C and

readonly C• C contains some methods that are absent from readonly C• given method may have different signatures in those two,

even though implementation is identical• keyword romaybe is provided• could be inferred, reducing explicit template annotations

Page 42: Javari: Adding Reference Immutability to Java Rauno Ots Matthew S. Tschantz Michael D. Ernst MIT CSAIL 2005.

Example

class DateCell {      Date value;

      void setValue(Date d) /*mutable*/ { value = d; }      romaybe Date getValue() romaybe { return value; }      static romaybe Date cellDate(romaybe DateCell c) {            return c.getValue();      }}

Page 43: Javari: Adding Reference Immutability to Java Rauno Ots Matthew S. Tschantz Michael D. Ernst MIT CSAIL 2005.

Code outside the type system

Reflection and serialization• is not checked by the Java type-checker, must be verified at

runtimeAt reflection• Method.invokeReadonly() must be called to get a readonly

ObjectAt serialization one extra bit is needed for writeObject() and readObject()

Page 44: Javari: Adding Reference Immutability to Java Rauno Ots Matthew S. Tschantz Michael D. Ernst MIT CSAIL 2005.

Other language features

• Interoperability with Java

• Type-based analyses

• Inner classeso readonly immediately following the parameter list of a

method or a constructor

•  Exceptions - cannot be readonly

•  Downcasts - runtime checks are added by compiler

Page 45: Javari: Adding Reference Immutability to Java Rauno Ots Matthew S. Tschantz Michael D. Ernst MIT CSAIL 2005.

Annotations instead of keywords

• compiles on any Java compiler

• runs on any JVM

• Javari as stand-alone type-checker

Page 46: Javari: Adding Reference Immutability to Java Rauno Ots Matthew S. Tschantz Michael D. Ernst MIT CSAIL 2005.

Annotations instead of keywords II

• Cannoto apply to a casto apply to the receiver (this) of a method

use new annotation @rothis on the methodo insert annotations into arbitrary location in arrays

(readonly Date[])[][] => @readonly(2) Date[][][]o use on type parameters 

Map<List<readonly Date>, readonly Set<Number>>

• Annotations on local variables are not recorded within the classfile by the javac compilero change the compilero Use custom comment syntax "/*="

Page 47: Javari: Adding Reference Immutability to Java Rauno Ots Matthew S. Tschantz Michael D. Ernst MIT CSAIL 2005.

Checker Framework

• enhances Java’s type system to make it more powerful and useful

• Javari checker is one of the checks• uses JSR 308 compiler (will be in Java 7)• Uses annotations(!)• Type inference tools exist to help you annotate your code• A programmer can write five

annotations: @ReadOnly, @Mutable, @Assignable, @PolyRead, and @QReadOnly

http://types.cs.washington.edu/checker-framework/

Page 48: Javari: Adding Reference Immutability to Java Rauno Ots Matthew S. Tschantz Michael D. Ernst MIT CSAIL 2005.

Conclusion

• Transitive reference immutability• Distinguishes assignability and mutability• Formal model• Type system for full Java including parametric

polymorphism, reflection, and serialization• Templates to reduce code duplication• Interoperable with Java