Difficult Specifications in Javari Immutability Inference Jaime Quinonez Program Analysis Group...

33
Difficult Specifications in Javari Immutability Inference Jaime Quinonez Program Analysis Group April 20, 2007

Transcript of Difficult Specifications in Javari Immutability Inference Jaime Quinonez Program Analysis Group...

Page 1: Difficult Specifications in Javari Immutability Inference Jaime Quinonez Program Analysis Group April 20, 2007.

Difficult Specifications in Javari Immutability Inference

Jaime QuinonezProgram Analysis Group

April 20, 2007

Page 2: Difficult Specifications in Javari Immutability Inference Jaime Quinonez Program Analysis Group April 20, 2007.

2

Overview

Overview of Javari Java with reference immutability

Overview of Javarifier Immutability reference algorithm

Cases with specifications that are hard to interpret Closed-world assumption Subtyping Conflicting, legal specifications

Correct specification depends on use

Page 3: Difficult Specifications in Javari Immutability Inference Jaime Quinonez Program Analysis Group April 20, 2007.

3

Reference Immutability in Java

For convenience, use annotations as type qualifiers

@ReadOnly on a type specifies a reference that cannot be used to modify an object

@ReadOnly can annotate any use of a type For a type T, @ReadOnly T is a supertype of

T @Mutable T is equivalent to T T can be used anywhere @ReadOnly T is expected @ReadOnly T cannot be used where T is expected

Page 4: Difficult Specifications in Javari Immutability Inference Jaime Quinonez Program Analysis Group April 20, 2007.

4

Example mutable class

setTime() mutates object getTime() does not mutate object

public class Date {private long time;

public Date(long t) {this.time = time;

}public long getTime() {

return time;}public void setTime(long time) {

this.time = time;}

}

Page 5: Difficult Specifications in Javari Immutability Inference Jaime Quinonez Program Analysis Group April 20, 2007.

5

@ReadOnly receiver annotates method

getTime() does not mutate object receiver of getTime() is @ReadOnly

public class Date {private long time;

public Date(long t) {this.time = time;

}public long getTime() @ReadOnly {

return time;}public void setTime(long time) {

this.time = time;}

}

Page 6: Difficult Specifications in Javari Immutability Inference Jaime Quinonez Program Analysis Group April 20, 2007.

6

Some fields not part of state

hashCode() does not modify abstract state hashCode() modifies a field

public class Date {private int hc;

public int hashCode() @ReadOnly {if(hc == 0) {

hc = … ;}return hc;

}}

Page 7: Difficult Specifications in Javari Immutability Inference Jaime Quinonez Program Analysis Group April 20, 2007.

7

@Assignable excludes fields from abstract state

hc is not part of abstract state

public class Date {private @Assignable int hc;

public int hashCode() @ReadOnly {if(hc == 0) {

hc = … ;}return hc;

}}

Page 8: Difficult Specifications in Javari Immutability Inference Jaime Quinonez Program Analysis Group April 20, 2007.

8

@ThisMutable gives fields mutability of containing reference

@ThisMutable is the default for all fields @ReadOnly Cell’s provide @ReadOnly Date references @Mutable Cell’s provide @Mutable Date references

public class Cell {public @ThisMutable Date d;

}

@ReadOnly Cell roCell;@Mutable Cell muCell;

roCell.d; // type: @ReadOnly DatemuCell.d; // type: @Mutable Date

Page 9: Difficult Specifications in Javari Immutability Inference Jaime Quinonez Program Analysis Group April 20, 2007.

9

@RoMaybe templates methods over mutability

All @RoMaybe’s can be replaced with all @ReadOnly or @Mutable

public class Cell {public @ThisMutable Date d;

public @RoMaybe Date get() @RoMaybe {return d;

}}@ReadOnly Cell roCell;@Mutable Cell muCell;

roCell.get(); // type: @ReadOnly Date, no rep exposuremuCell.get(); // type: @Mutable Date, have rep exposure

Page 10: Difficult Specifications in Javari Immutability Inference Jaime Quinonez Program Analysis Group April 20, 2007.

10

Javarifier : Type Inference Algorithm

Flow-insensitive and context-insensitive Generate a set of mutability constraints

Unguarded constraint states unconditional mutability

• “x is mutable” Guarded constraint states conditional mutability

• “if x is mutable, then y is mutable” Solve set of constraints to see what types have

to be mutable All other types can safely be declared immutable

Page 11: Difficult Specifications in Javari Immutability Inference Jaime Quinonez Program Analysis Group April 20, 2007.

11

Field reassignment mutates object Create unguarded constraint

public class Date {private long time;public Date(long time) {

this.time = time}public void setTime(long time) {

this.time = time;}public long getTime() {

return time;}

}

Page 12: Difficult Specifications in Javari Immutability Inference Jaime Quinonez Program Analysis Group April 20, 2007.

12

Field reassignment mutates object Create unguarded constraint

public class Date {private long time;public Date(long time) {

this.time = time}public void setTime(long time) {

this.time = time;}public long getTime() {

return time;}

}

Date.setTime().this is mutable

Page 13: Difficult Specifications in Javari Immutability Inference Jaime Quinonez Program Analysis Group April 20, 2007.

13

Calling methods on fields Create guarded constraint based on field’s typepublic class Cell {

private Date d;

public long get() {return d.getTime();

}

public void reset() {d.setTime(0);

}}

Page 14: Difficult Specifications in Javari Immutability Inference Jaime Quinonez Program Analysis Group April 20, 2007.

14

Calling methods on fields Create guarded constraint based on field’s typepublic class Cell {

private Date d;

public long get() {return d.getTime();

}

public void reset() {d.setTime(0);

}}

Page 15: Difficult Specifications in Javari Immutability Inference Jaime Quinonez Program Analysis Group April 20, 2007.

15

Calling methods on fields Create guarded constraint based on field’s typepublic class Cell {

private Date d;

public long get() {return d.getTime();

}

public void reset() {d.setTime(0)

}}

Date.getTime().this mutable -> Cell.d mutable Date.getTime().this mutable -> Cell.get().this mutable

Page 16: Difficult Specifications in Javari Immutability Inference Jaime Quinonez Program Analysis Group April 20, 2007.

16

Calling methods on fields Create guarded constraint based on field’s typepublic class Cell {

private Date d;

public long get() {return d.getTime();

}

public void reset() {d.setTime(0);

}}

Date.getTime().this mutable -> Cell.d mutable Date.getTime().this mutable -> Cell.get().this mutable

Page 17: Difficult Specifications in Javari Immutability Inference Jaime Quinonez Program Analysis Group April 20, 2007.

17

Calling methods on fields Create guarded constraint based on field’s typepublic class Cell {

private Date d;

public long get() {return d.getTime();

}

public void reset() {d.setTime(0);

}}

Date.getTime().this mutable -> Cell.d mutable Date.getTime().this mutable -> Cell.get().this mutable Date.setTime().this mutable -> Cell.d mutable Date.setTime().this mutable -> Cell.reset().this mutable

Page 18: Difficult Specifications in Javari Immutability Inference Jaime Quinonez Program Analysis Group April 20, 2007.

18

Javarifier propagates unguarded constraints Constraints

1. Date.setTime().this is mutable2. Date.getTime().this mutable -> Cell.d mutable3. Date.getTime().this mutable -> Cell.get().this mutable4. Date.setTime().this mutable -> Cell.d mutable5. Date.setTime().this mutable -> Cell.reset().this

mutable1. New Constraints

1. Cell.reset().this is mutable2. Cell.d is mutable

Final unguarded constraints1. Date.setTime().this is mutable2. Cell.reset().this is mutable3. Cell.d is mutable4. All other types are @ReadOnly

Page 19: Difficult Specifications in Javari Immutability Inference Jaime Quinonez Program Analysis Group April 20, 2007.

19

Closed-world assumption causes ambiguity

Javarifier assumes that all classes in the system are known All classes are implemented All interfaces and abstract classes have some implementation If any part of the system changes, all annotations become

invalid If an implementation is missing, nothing can be done Whatever is inferred, programmer can claim the opposite

should be true

public class C {public void foo(Object o) {

throw new RuntimeException();}

}

public interface A {Object void bar();

}

Page 20: Difficult Specifications in Javari Immutability Inference Jaime Quinonez Program Analysis Group April 20, 2007.

20

Subclasses must inherit mutability exactly Mutability is part of the method signature A defines method foo with no body, B and C extend A and provide

implementation C.foo(List) modifies its argument, B.foo(List) does not

public abstract class A {abstract void foo(List arg);

}

public class B extends A {void foo(List arg) { }

}

public class C extends A {void foo(List arg) {

arg.clear();}

}

Page 21: Difficult Specifications in Javari Immutability Inference Jaime Quinonez Program Analysis Group April 20, 2007.

21

Subclasses must inherit mutability exactly C.foo(List) must take a mutable parameter, so all definitions of

foo must take a mutable parameter If you only examined output on class A and B, mutability wouldn’t

make sense

public abstract class A {abstract void foo(@Mutable List arg);

}

public class B extends A {void foo(@Mutable List arg) { }

}

public class C extends A {void foo(@Mutable List arg) {

arg.clear();}

}

Page 22: Difficult Specifications in Javari Immutability Inference Jaime Quinonez Program Analysis Group April 20, 2007.

22

Alternative annotations on a class

Cell wraps around a Date object, which makes up its abstract state

set() clearly modifies the abstract state of the object get() does not modify the abstract state, but does expose it

public class Cell {private Date d;

public void set(Date d) {this.d = d;

}

public Date get() {return d;

}}

Page 23: Difficult Specifications in Javari Immutability Inference Jaime Quinonez Program Analysis Group April 20, 2007.

23

Alternative annotations on a class Field d is this-mutable set() has a mutable ‘this’, so this.d is mutable and thus

parameter is mutable get() returns a Date of the same mutability as what is passed

in Can only insert mutable Dates

public class Cell {private @ThisMutable Date d;

public void set(@Mutable Date d) @Mutable {this.d = d;

}

public @RoMaybe Date get() @RoMaybe {return d;

}}

Page 24: Difficult Specifications in Javari Immutability Inference Jaime Quinonez Program Analysis Group April 20, 2007.

24

Alternative annotations on a class Field d is readonly set() still mutates its receiver, but now accepts a

readonly Date get() can only return a readonly Date Can only get back readonly Dates

public class Cell {private @ReadOnly Date d;

public void set(@ReadOnly Date d) @Mutable {this.d = d;

}

public @ReadOnly Date get() @ReadOnly {return d;

}}

Page 25: Difficult Specifications in Javari Immutability Inference Jaime Quinonez Program Analysis Group April 20, 2007.

25

Alternative annotations on a class Field d is mutable set() still mutates its receiver, must take a mutable Date get() can return a mutable Date Can only insert mutable Dates

public class Cell {private @Mutable Date d;

public void set(@Mutable Date d) @Mutable {this.d = d;

}

public @Mutable Date get() @ReadOnly {return d;

}}

Page 26: Difficult Specifications in Javari Immutability Inference Jaime Quinonez Program Analysis Group April 20, 2007.

26

Field can be excluded from abstract state Field d is assignable and this-mutable set() does not change the abstract state of the object get() can only return mutable Date Can only return mutable Dates

public class Cell {private @Assignable @ThisMutable Date d;

public void set(@ReadOnly Date d) @ReadOnly {this.d = d;

}

public @ReadOnly Date get() @ReadOnly {return d;

}}

Page 27: Difficult Specifications in Javari Immutability Inference Jaime Quinonez Program Analysis Group April 20, 2007.

27

Field can be excluded from abstract state Field d is assignable and mutable, completely excluded from

abstract state set() does not change the abstract state of the object get() can return a mutable Date Can only insert mutable Dates

public class Cell {private @Assignable @Mutable Date d;

public void set(@Mutable Date d) @ReadOnly {this.d = d;

}

public @Mutable Date get() @ReadOnly {return d;

}}

Page 28: Difficult Specifications in Javari Immutability Inference Jaime Quinonez Program Analysis Group April 20, 2007.

28

‘this’ is mutable inside constructor If field d is this-mutable, then constructor must accept mutable

parameter Can’t even construct a Cell without a mutable Date

public class Cell {private @ThisMutable Date d;

public Cell(@Mutable Date d) {this.d = d;

}

public void set(@Mutable Date d) @Mutable {this.d = d;

}

public @RoMaybe Date get() @RoMaybe {return d;

}}

Page 29: Difficult Specifications in Javari Immutability Inference Jaime Quinonez Program Analysis Group April 20, 2007.

29

Many possibilities can be correct

All of the previous annotated classes are valid Javari

Will type-check when compiling Cell.java The ‘correct’ set of annotations is that which

satisfy the contract that other code requires Closed-world assumption: Know all uses of class If you don’t need to mutate the result of get(), can

have every Date in Cell be @ReadOnly If you will only be inserting mutable Dates, can have

every Date in Cell be @Mutable

Page 30: Difficult Specifications in Javari Immutability Inference Jaime Quinonez Program Analysis Group April 20, 2007.

30

Can excluding fields from state be inferred?

Not likely

Page 31: Difficult Specifications in Javari Immutability Inference Jaime Quinonez Program Analysis Group April 20, 2007.

31

Excluding a field from state can break equals() Field d is assignable and mutable, completely excluded from

abstract state Calling a readonly method changes which objects this is

equal to

public class Cell {private @Assignable @Mutable Date d;

public void set(@Mutable Date d) @ReadOnly {this.d = d;

}

public boolean equals(Object o) {// true iff o is a Cell and this.d.equals(o.d)

}}

Page 32: Difficult Specifications in Javari Immutability Inference Jaime Quinonez Program Analysis Group April 20, 2007.

32

Can excluding fields from state be inferred?

Not likely A feasible heuristic is to exclude fields not used

in equals() Debug/log information can be read/modified in equals() Debug/log fields are the ones you can reasonably exclude Might also have variables not read in equals() that can

change abstract state Counters decremented every method call that once they

timeout, will change part of state A shallow equals() could omit information read in

toString() User doesn’t want toString() to return different Strings

between calls to readonly methods

Page 33: Difficult Specifications in Javari Immutability Inference Jaime Quinonez Program Analysis Group April 20, 2007.

33

Customizing Javarifier results

User could annotate certain fields individually as not being part of the state of the class, and Javarifier can trust those annotations

Presently, user can only annotate whole classes (unannotated elements take their default mutability)

Can annotate all the methods in a Logger class to be readonly

A general framework for specifying user versus inferred annotations is being investigated