Ownership and immutability in generic java oigj
This presentation is the property of its rightful owner.
Sponsored Links
1 / 33

Ownership and Immutability in Generic Java (OIGJ) PowerPoint PPT Presentation


  • 114 Views
  • Uploaded on
  • Presentation posted in: General

Yoav Zibin + , Alex Potanin * Paley Li * , Mahmood Ali ^ , and Michael Ernst $ Presenter: Yossi Gil + + IBM * Victoria,NZ ^ MIT $ Washington. Ownership and Immutability in Generic Java (OIGJ). Ownership + Immutability. Our previous work OGJ: added Ownership to Java

Download Presentation

Ownership and Immutability in Generic Java (OIGJ)

An Image/Link below is provided (as is) to download presentation

Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author.While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server.


- - - - - - - - - - - - - - - - - - - - - - - - - - E N D - - - - - - - - - - - - - - - - - - - - - - - - - -

Presentation Transcript


Ownership and immutability in generic java oigj

YoavZibin+, Alex Potanin*

Paley Li*, Mahmood Ali^, and Michael Ernst$

Presenter: Yossi Gil+

+IBM *Victoria,NZ^MIT $Washington

Ownership and Immutability in Generic Java (OIGJ)


Ownership immutability

Ownership + Immutability

Our previous work

OGJ: added Ownership to Java

IGJ: added Immutability to Java

This work

OIGJ: combine Ownership + Immutability

The sum is greater than its parts

IGJ could not type-check existing code for creating immutable cyclic data-structures (e.g., lists, trees)

We found a non-trivial connection between ownership and immutability


Contributions

Contributions

No refactoring of existing code

Prototype implementation

No syntax changes (uses type-annotations in Java 7)

No runtime overhead

Backward compatible

Verified that Java’s collection classes are properly encapsulated (using few annotations)

Flexibility

OIGJ can type-check more code than previous work: cyclic structures, the factory and visitor design patterns

Formalization

Formalized the concepts of raw/cooked immutable objects and wildcards as owner parameters

Proved soundness


Problem 1 representation exposure

Problem 1: Representation exposure

Internal representation leaks to the outside

private doesn’t offer real protection!

Real life example!

class Class {

private List signers;

public List getSigners() {

return this.signers;

}

}

Forgot to copy signers!

  • http://java.sun.com/security/getSigners.html

  • Bug: the system thinks that code signed by one identity is signed by a different identity


Solution for representation exposure

Solution for Representation Exposure

Ownership!

Class should own the list signers

No outside alias can exist

Ownership can be nested: note the tree structure

Class

X

signers

X

entry1

entry2

entryN

X

elem1

elem2

elemN


Ownership owner as dominator

Ownership: Owner-as-dominator

Dominators in graph theory

Given: a directed rooted graph

X dominates Y if any path from the root to Y passes X

Owner-as-dominator

Object graph; roots are the static variables

An object cannot leak outside its owner, i.e.,

Any path from a root to an object passes its owner

Conclusion: No aliases to internal state


Problem 2 unintended modification

Problem 2: Unintended Modification

Modification is not explicit in the language

can Map.get() modify the map?

for (Object key : map.keySet()) { map.get(key); }throwsConcurrentModificationExceptionfor the following mapnew LinkedHashMap(100, 1, true)

Reorders elements according to last-accessed (like a cache)


Solution immutability

Solution: Immutability

Varieties of Immutability

Class immutability (like String or Integer in Java)

Object immutability

The same class may have both mutable and immutable instances

Reference immutability

A particular reference cannot be used to mutate its referent (but other aliases might cause mutations)

Example in IGJ syntax

class Student {

@Immutable Date dateOfBirth; …

void setTutor(@ReadOnly Student tutor) @Mutable { … }

}

Method may modify the this object


Objects vs references

Objects vs. References

Objects

mutable or immutable

Creation of an immutable object

Raw state: Fields can be assigned

Cooked state: Fields cannot be assigned

References

mutable, immutable, or readonly


Challenge cyclic immutability

Challenge: Cyclic Immutability

  • Cooking a cyclic data-structure is complicated

    • Many objects must be raw simultaneously to manipulate backward pointers

    • Then everything must become immutable simultaneously

  • OIGJ’s novel idea:

    • Prolong the cooking phase by using ownership information

    • Enables creation of immutable cyclic structures


Cooking immutable objects

Cooking immutable objects

Previous work

An object becomes cooked when its constructor finishes

OIGJ’s observation

An object becomes cooked when its owner’s constructor finishes

The outside world will not see this cooking phase

The complex object with its representation becomes immutable simultenously


Cooking linkedlist 1 of 2

Cooking LinkedList (1 of 2)

No refactoring – the original code must compile in OIGJ

Sun’s code is similar

1 : LinkedList(Collection<E> c){

2 : this();

3 : Entry<E> succ = this.header, pred = succ.prev;

4 : for (E e : c) {

5 : Entry<E> entry =

6 : new Entry<E>(e,succ,pred);

7 : // An entry is modified after it’s constructor finished

8 : pred.next = entry; pred = entry;

9 : }

10: succ.prev= pred;

11: }


Cooking linkedlist 2 of 2

Cooking LinkedList (2 of 2)

The list owns its entries

Therefore, it can mutate them, even after their constructor finished

Sun’s code is similar

1 : LinkedList(@ReadOnlyCollection<E> c) @Raw {

2 : this();

3 : @This @I Entry<E> succ = this.header, pred = succ.prev;

4 : for (E e : c) {

5 : @This @I Entry<E> entry =

6 : new @This @I Entry<E>(e,succ,pred);

7 : // An entry is modified after it’s constructor finished

8 : pred.next = entry; pred = entry;

9 : }

10: succ.prev= pred;

11: }

Code in OIGJ; Annotations next slide.


Hierarchies in oigj

Hierarchies in OIGJ

ReadOnly

World

Raw

Immut

This

Mutable

Ownership hierarchy

World – anyone can access

This – this owns the object

Immutability hierarchy

ReadOnly– no modification

Raw– object under

construction


Oigj syntax fields 1 of 2

OIGJ syntax: fields (1 of 2)

Two annotations per type

1:class Foo{

2: // An immutable reference to an immutable date.

@O @ImmutDate imD = new @O @ImmutDate ();

3: // A mutable reference to a mutable date.

@O @Mutable Date mutD = new @O @Mutable Date();

4: // A readonly reference to any date. Both roD and imD cannot mutate

// their referent, however the referent of roD might be mutated by an

// alias, whereas the referent of imD is immutable.

@O @ReadOnlyDate roD= ... ? imD : mutD;

5: //A date with the same owner and immutability asthis

@O @I Date sameD;

6: // A date owned bythis; it cannot leak.

@This @I Date ownedD;

7: // Anyone can access this date.

@World @I Date publicD;


Oigj syntax methods 2 of 2

OIGJ syntax: methods (2 of 2)

Method receiver’s annotation has a dual purpose:

Determines if the method is applicable.

Inside the method, the bound of @Iis the annotation.

8 : // Can be called on any receiver; cannot mutate this.

intreadonlyMethod() @ReadOnly{...}

9 : // Can be called only on mutable receivers; can mutate this.

void mutatingMethod() @Mutable {...}

10: // Constructor that can create (im)mutable objects.

Foo(@O @I Date d) @Raw {

11: this.sameD = d;

12: this.ownedD = new @This @I Date ();

13: // Illegal, because sameDcame from the outside.

// this.sameD.setTime(...);

14: // OK, because Rawis transitive for owned fields.

this.ownedD.setTime(...);

15: }


Formalization featherweight oigj

Formalization: Featherweight OIGJ

  • Novel idea: Cookers

    • Every location l in the heap is of the form:

    • l' is the owner of l

    • l” is the cooker of l, i.e., when the constructor of l” finishes then l becomes cooked

    • We keep track of the set of ongoing constructors

    • Subtyping rules connect cookers and owners

or

lFoo<l’,Mutable>

lFoo<l’,Immut >

l"

  • Proved soundness and type preservation


Case studies

Case studies

  • Implementation uses the checkers framework

    • Only 1600 lines of code (but still a prototype)

    • Requires type annotations available in Java 7

  • Java’s Collections case study

    • 77 classes, 33K lines of code

    • 85 ownership-related annotations

    • 46 immutability-related annotations


Case studies conclusions

Case studies conclusions

  • Verified that collections own their representation

    • Method clone is problematic

    • Clone makes a shallow copy that breaks ownership

    • Our suggestion: compiler-generated clone that nullifies fields, and then calls a copy-constructor


Previous work

Previous Work

Universes

Relaxed owner-as-dominator to owner-as-modifier

ReadOnly references can be freely shared

Constrains modification instead of aliasing, i.e., only the owner can modify an object

Reference immutability:

C++’s const

Javari


Future work

Future work

Inferring ownership and immutability annotations

Bigger case study

Extending OIGJ

owner-as-modifier

uniqueness or external uniqueness


Conclusions

Conclusions

  • Ownership Immutability Generic Java (OIGJ)

    • Simple, intuitive, small

    • Static – no runtime penalties (like generics)

    • Backward compatible, no JVM changes

  • Case study proving usefulness

  • Formal proof of soundness

  • Paper submitted to OOPSLA. Links:

    • http://ecs.victoria.ac.nz/twiki/pub/Main/TechnicalReportSeries/

    • http://code.google.com/p/checker-framework/

    • http://code.google.com/p/ownership-immutability/


Oigj typing rules

OIGJ typing rules

Ownership nesting

Field access

Field assignment

Method invocation

Method guards

Raw parameter

can be used only in method guards

(see the paper for all rules, such as inner classes, covariant subtyping)


Ownership example in ogj

Ownership example in OGJ

This-owned fields/methods can be accessed only via this

class Class {

@This List signers; // This-owned field

public @This List getSigners1() {

return this.signers;

}

public @World List getSigners2() {

return new @World LinkedList(this.signers);

}

public void example(Class other) {

this.signers = …; // Ok

other.signers = …; // Illegal

this.getSigners1(); // Ok

other.getSigners1(); // Illegal

other.getSigners2(); // Ok

}


Oigj syntax fields 1 of 21

OIGJ syntax: fields (1 of 2)

Two new generic parameters were added

1:class Foo<O extends World, I extends ReadOnly> {

2: // An immutable reference to an immutable date.

Date<O,Immut>imD = new Date<O,Immut>();

3: // A mutable reference to a mutable date.

Date<O,Mutable>mutD = new Date<O,Mutable>();

4: // A readonly reference to any date. Both roD and imD cannot mutate

// their referent, however the referent of roD might be mutated by an

// alias, whereas the referent of imD is immutable.

Date<O,ReadOnly>roD = ... ? imD : mutD;

5: // A date with the same owner and immutability as this

Date<O,I>sameD;

6: // A date owned by this; it cannot leak.

Date<This,I>ownedD;

7: // Anyone can access this date.

Date<World,I>publicD;


Oigj syntax methods 2 of 21

OIGJ syntax: methods (2 of 2)

Method guard <T extends U>?has a dual purpose:

The method is included only if T extends U

Inside the method, the bound of Tis U.

8 : // Can be called on any receiver; cannot mutate this.

<I extends ReadOnly>? intreadonlyMethod(){...}

9 : // Can be called only on mutable receivers; can mutate this.

<I extends Mutable>? void mutatingMethod(){...}

10: // Constructor that can create (im)mutable objects.

<I extends Raw>? Foo(Date<O,I> d) {

11: this.sameD = d;

12: this.ownedD = new Date<This,I>();

13: // Illegal, because sameDcame from the outside.

// this.sameD.setTime(...);

14: // OK, because Raw is transitive for owned fields.

this.ownedD.setTime(...);

15: }


Linkedlist example

LinkedList Example

1 : class Entry<O,I,E> {

2 : E element;

3 : Entry<O,I,E> next, prev; …

4 : }

5 : class LinkedList<O,I,E> {

6 : Entry<This,I,E> header; …

7 : <I extends Raw>?LinkedList(

8 : Collection<?,ReadOnly,E> c) {

9 : this(); this.addAll(c);

10: }

11: <I extends Raw>? void addAll(

12: Collection<?,ReadOnly,E> c) {

13: Entry<This,I,E> succ = this.header,

14: pred = succ.prev;

15: for (E e : c) {

16: Entry<This,I,E> en =

17: new Entry<This,I,E>(e,succ,pred);

18: pred.next = en; pred = en; }

19: succ.prev = pred;

20: }


Ownership nesting

Ownership nesting

The main owner parameter must be inside any other owner parameter.

List<This, I,Date<World,I>> l1; // Legal nesting

List<World,I,Date<This, I>> l2; // Illegal!

It’s illegal because we can store l2 in this variable:

public static Object<World,ReadOnly> alias_l2;


Field access assignment

Field access/assignment

this-owned fields can be accessed/assigned only via this

1: class Foo<O extends World, I extends ReadOnly> {

2: Date<This,I> ownedD; // this-owned field

3: Date<O,I> sameD;

4: <I extends Mutable>? void bar(Foo<This,I> other) {

5: this.ownedD = …; // Legal: assign via this

6: other.ownedD = …; // Illegal: not via this

7: other.sameD = …; // Legal: not this-owned

8: }


Field assignment

Field assignment

A field can be assigned only if the object is Raw or Mutable.

If it is Raw, then the object must be this or this-owned.

1 : class Foo<O extends World, I extends ReadOnly> {

2 : Date<O,I> sameD;

3 : <I extends Raw>? void bar(

4 : Foo<?,Mutable> mutableFoo,

5 : Foo<?,ReadOnly> readonlyFoo,

6 : Foo<?,I> rawFoo1,

7 : Foo<This,I> rawFoo2) {

8 : mutableFoo.sameD = …; // Legal: object is Mutable

9 : readonlyFoo.sameD = …; // Illegal: object is not Raw nor Mutable

10: rawFoo1.sameD = …; // Illegal: object is not this nor this-owned

11: rawFoo2.sameD = …; // Legal: object is Raw and this-owned

12: this.sameD = …; // Legal: object is Raw and this

13: }


Method invocation

Method invocation

Method invocation is the same as field access/assignment:

If any parameter is this-owned, then the receiver must be this.

If the guard is Raw and the object is Raw, then the receiver must be this or this-owned.

1 : class Foo<O extends World, I extends ReadOnly> {

2 : Date<This,I> m1() { … } // Parameter is this-owned

3 : <I extends Raw>? void m2() { … }

4 : <I extends Raw>? void bar(

5 : Foo<?,I> rawFoo1,

6 : Foo<This,I> rawFoo2) {

7 : this.m1(); // Legal: object is this

8 : rawFoo2.m1(); // Illegal: object is not this

9 : rawFoo1.m2(); // Illegal: object is not this nor this-owned

10: rawFoo2.m2(); // Legal: both Raw and object is this-owned

11: this.m2(); // Legal: both Raw and object is this

12: }


Method guards

Method guards

Guard “<T extends U>?” has a dual purpose:

The receiver’s T must be a subtype of U.

Inside the method, the bound of T is U.

1: class Foo<O extends World, I extends ReadOnly> {

2: <I extends Raw>? void rawM() { … }

3: <I extends Mutable>? void bar(

4: Foo<?,ReadOnly> readonlyFoo,

5: Foo<?,I> mutableFoo) {

6: readonlyFoo.rawM(); // Illegal: ReadOnly is not a subtype of Raw

// The bound of I in this method is Mutable

7: mutableFoo.rawM(); // Legal: Mutableis a subtype of Raw

8: this.rawM(); // Legal: Mutable is a subtype of Raw

9: }

Conditional Java (cJ) proposed method guards for Java


  • Login