Download presentation
Presentation is loading. Please wait.
Published byGertrude Mitchell Modified over 9 years ago
1
Javari: Adding Reference Immutability to Java Rauno Ots Matthew S. Tschantz Michael D. Ernst MIT CSAIL 2005
2
Intro 1.Immutability 2.Motivation 3.Javari 4.Formalization 5.Some problems o Templetizing o Annotations 6.Checker framework
3
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
4
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
5
Motivation - Example 1 ElectionResults tabulate(Ballots votes) {... } vs ElectionResults tabulate(readonly Ballots votes) {... // cannot tamper with the votes }
6
Motivation - Example 2 class FileSystem { private List inodes; List getInodes() {... // Unrealistic to copy } vs class FileSystem { private List inodes; readonly List getInodes(){... }
7
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;
8
Javari 1.Assignability 2.Mutability 3.Fields: this-assignable and this-mutable 4.Generics 5.Arrays 6.Summary
9
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
10
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(); // OK rodate.setYear(2005); // error
11
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; // OK rodate = (readonly Date) date; // OK date = rodate; // error date = (Date) rodate; // error: Java cast cannot make a readonly reference mutable
12
Mutability III readonly can be used in a declaration of any local variable, field, parameter or method return type by default, mutable o except fields o 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
13
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 }
14
Mutability: Overloading Identical to Java (except the mutability of receiver) Performed in two steps 1.Compile-time (overloaded) Finds most specific signature No matching signatures or no single most specific match issues a compile-time error 2.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
15
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 2.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
16
Mutability: Immutable classes Class or interface can be declared readonly o 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
17
Fields: this-assignable and this-mutable By default field inherits from accessed reference o if accessed through read-only reference then unassignable and read-only o 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 mutable to exclude specific fields from the object’s abstract state.
18
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
19
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 }
20
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; }
21
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; }
22
Assignable fields (Loophole solution) Even if used through readonly reference, the this-mutable field is potentially mutable Can assign only mutable references
23
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 log; int hashCode() readonly { // OK: log is mutable log.add("entered hashCode()");... }
24
Generic classes /*mutable*/ List ld1; // add/rem./mut. /*mutable*/ List ld2; // add/remove readonly List ld3; // mutate readonly List ld4; // (neither) class DateList { // 3 readonly lists whose elements have different mutability readonly List lst; readonly List lst2; readonly List lst3; }
25
Generic classes II class Foo { // 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 ();
26
Arrays Nothing special Date [] ad1;//add/remove, mutate (readonly Date)[] ad2;//add/remove readonly Date [] ad3;//mutate readonly (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 types Date[] b=new Date[2]; Object[] a=b; //OK a[0]=new Object();//Runtime error ad2 = ad1; //error
27
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
28
Summary
29
Formalization 1.Featherweight Generic Java to Lightweight Java o field assignment o the final keyword 2.Lightweight Java to Lightweight Javari o reference immutability
30
Lightweight Java syntax
31
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
32
LJ syntax S, T, U, V - types X, Y, Z - type variables N, P, Q - nonvariable types C - unparametherized class names f,g - field names AF - assignability of fields K - constructor declaration M - method declaration e - expression x - variable
33
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 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, 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, T → T) - method m with type 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.
34
Lightweight Java
35
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.
36
Lightweight Java
37
Lightweight Javari
38
Every type is is modified by one of the mutability modifiers: readonly, mutable or (for fields) this-mutable. Addition of this-assignable keyword
39
Lightweight Javari
41
Templatizing methods over mutability to 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
42
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(); }
43
Code outside the type system Reflection and serialization is not checked by the Java type-checker, must be verified at runtime At reflection Method.invokeReadonly() must be called to get a readonly Object At serialization one extra bit is needed for writeObject() and readObject()
44
Other language features Interoperability with Java Type-based analyses Inner classes o readonly immediately following the parameter list of a method or a constructor Exceptions - cannot be readonly Downcasts - runtime checks are added by compiler
45
Annotations instead of keywords compiles on any Java compiler runs on any JVM Javari as stand-alone type-checker
46
Annotations instead of keywords II Cannot o apply to a cast o apply to the receiver (this) of a method use new annotation @rothis on the method o insert annotations into arbitrary location in arrays (readonly Date[])[][] => @readonly(2) Date[][][] o use on type parameters Map, readonly Set > Annotations on local variables are not recorded within the classfile by the javac compiler o change the compiler o Use custom comment syntax "/*="
47
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, @Poly Read, and @QReadOnly http://types.cs.washington.edu/checker- framework/
48
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
Similar presentations
© 2025 SlidePlayer.com. Inc.
All rights reserved.