javarifier inference of reference immutability
play

Javarifier: inference of reference immutability Jaime Quinonez - PowerPoint PPT Presentation

print(Object x) { print( @Readonly Object x) { } } Javarifier: inference of reference immutability Jaime Quinonez Matthew S. Tschantz Michael D. Ernst MIT Security code in JDK 1.1 class Class { private Object[] signers;


  1. print(Object x) { print( @Readonly Object x) { … … } } Javarifier: inference of reference immutability Jaime Quinonez Matthew S. Tschantz Michael D. Ernst MIT

  2. Security code in JDK 1.1 class Class { private Object[] signers; Object[] getSigners() { return signers; } }

  3. Security code in JDK 1.1 class Class { private Object[] signers; Object[] getSigners() { return signers; } } myClass.getSigners()[0] = “Sun”;

  4. Immutability annotations prevent mutation errors class Class { private Object[] signers; // Prohibits client from mutating @Readonly Object[] getSigners() { return signers; } } myClass.getSigners()[0] = “Sun”; // Error

  5. Immutability annotations prevent mutation errors class Class { // Forces getSigners to return a copy private @Readonly Object[] signers; Object[] getSigners() { return signers; // Error } } myClass.getSigners()[0] = “Sun”;

  6. Reasoning about side effects • Machine-checked formal documentation • Error detection • Verification • Enables analyses • Enables transformations and optimizations • Case studies: expressive, natural, useful – 300 KLOC of programmer-written code

  7. Type-checking requires annotations • Easy for new programs • Tedious for legacy programs • Worst for libraries: large, hard to understand • Library annotations cannot be omitted // Assume user program is fully annotated @Readonly MyClass x = …; x.toString(); // OK x.mutate(); // Error System.out.println(x); // False error! • Library declares println as: void println (Object) { … } • But it should be: void println(@Readonly Object) { … }

  8. Immutability inference algorithm • Sound • Precise (complete) • Linear time • Rich, practical type system: Javari [Tschantz 2005] • Context-sensitive – Type polymorphism (Java generics and wildcards) – Mutability polymorphism (type qualifier polymorphism) – Containing-object context (deep immutability) • Infers abstract state • Handles partially-annotated code, unanalyzable code

  9. Immutability inference implementation • Implements the full algorithm • Handles all of Java • Works on bytecodes • Inserts results in source or .class file • Scales to >100 KLOC • Verified by independent typechecker • Verified by comparison to other tools • Publicly available: – http://pag.csail.mit.edu/javari/javarifier/

  10. Javari type system • A given reference cannot be used to modify its referent – Other references to the object may modify it • Deep: the transitively reachable state (the abstract state) is protected • Generics: List<@Readonly Date> • Mutability polymorphism: @Polyread Object id(@Polyread arg) { return arg; }

  11. Algorithm: propagate mutability • Syntax-directed constraint generation • Unconditional constraint: x – x is mutable – Example code: x.field = 22; • Conditional constraint: y  z – if y is mutable, then z is mutable – Example code: y = z; • Constraint solving: graph reachability – Unmarked references remain readonly

  12. Appointment class class Appt { Receivers are written explicitly private Date d; void setDate(Appt this, Date newDate) { this.d = newDate; } Date getDate(Appt this) { class Date { Date result = this.d; private long time; return result; } … void reset(Appt this) { void setTime(Date this, long newTime) { Date thisDate = this.d; this.time = newTime; setTime(thisDate, 0); } } } }

  13. Assignment class Appt { Sample code: x.f = y; private Date d; Constraints: { x, void setDate(Appt this, f  y } Date newDate) { this.d = newDate; } Date getDate(Appt this) { class Date { Date result = this.d; private long time; return result; } … void reset(Appt this) { void setTime(Date this, long newTime) { Date thisDate = this.d; this.time = newTime; setTime(thisDate, 0); } } } }

  14. Assignment class Appt { Sample code: x.f = y; private Date d; Constraints: { x, void setDate(Appt this, f  y } Date newDate) { this.d = newDate; } Date getDate(Appt this) { class Date { Date result = this.d; private long time; return result; } … void reset(Appt this) { void setTime(Date this, long newTime) { Date thisDate = this.d; this.time = newTime; setTime(thisDate, 0); } } } }

  15. Assignment class Appt { Sample code: x.f = y; private Date d; Constraints: { x, void setDate(Appt this , f  y } Date newDate) { this.d = newDate; } Date getDate(Appt this) { class Date { Date result = this.d; private long time; return result; } … void reset(Appt this) { void setTime(Date this, long newTime) { Date thisDate = this.d; this.time = newTime; setTime(thisDate, 0); } } } }

  16. Assignment class Appt { Sample code: x.f = y; private Date d; Constraints: { x, void setDate(Appt this , f  y } Date newDate) { this.d = newDate; } Date getDate(Appt this) { class Date { Date result = this.d; private long time; return result; } … void reset(Appt this) { void setTime(Date this, long newTime) { Date thisDate = this.d; this.time = newTime; setTime(thisDate, 0); } } } }

  17. Dereference class Appt { Sample code: x = y.f; private Date d; { x  f, Constraints: void setDate(Appt this, x  y } Date newDate) { this.d = newDate; } Date getDate(Appt this) { class Date { Date result = this.d; private long time; return result; } … void reset(Appt this) { void setTime(Date this, long newTime) { Date thisDate = this.d; this.time = newTime; setTime(thisDate, 0); } } } }

  18. Dereference class Appt { Sample code: x = y.f; private Date d; { x  f, Constraints: void setDate(Appt this, x  y } Date newDate) { this.d = newDate; } Date getDate(Appt this) { class Date { Date result = this.d; private long time; return result; } … void reset(Appt this) { void setTime(Date this, long newTime) { Date thisDate = this.d; this.time = newTime; setTime(thisDate, 0); } } } }

  19. Dereference class Appt { Sample code: x = y.f; private Date d; { x  f, Constraints: void setDate(Appt this, x  y } Date newDate) { this.d = newDate; } Date getDate(Appt this) { class Date { Date result = this.d; private long time; return result; } … void reset(Appt this) { void setTime(Date this, long newTime) { Date thisDate = this.d; this.time = newTime; setTime(thisDate, 0); } } } }

  20. Dereference class Appt { Sample code: x = y.f; private Date d; { x  f, Constraints: void setDate(Appt this, x  y } Date newDate) { this.d = newDate; } Date getDate(Appt this) { class Date { Date result = this.d; private long time; return result; } … void reset(Appt this) { void setTime(Date this, long newTime) { Date thisDate = this.d; this.time = newTime; setTime(thisDate, 0); } } } }

  21. Method invocation class Appt { Sample code: x = m(y1); private Date d; { param1  y1, Constraints: void setDate(Appt this, x  ret } Date newDate) { this.d = newDate; } Date getDate(Appt this) { class Date { Date result = this.d; private long time; return result; } … void reset(Appt this) { void setTime(Date this, long newTime) { Date thisDate = this.d; this.time = newTime; setTime(thisDate, 0); } } } }

  22. Method invocation class Appt { Sample code: x = m(y1); private Date d; { param1  y1, Constraints: void setDate(Appt this, x  ret } Date newDate) { this.d = newDate; } Date getDate(Appt this) { class Date { Date result = this.d; private long time; return result; } … void reset(Appt this) { void setTime(Date this, long newTime) { Date thisDate = this.d; this.time = newTime; setTime(thisDate, 0); } } } }

  23. Method invocation class Appt { Sample code: x = m(y1); private Date d; { param1  y1, Constraints: void setDate(Appt this, x  ret } Date newDate) { this.d = newDate; } Date getDate(Appt this) { class Date { Date result = this.d; private long time; return result; } … void reset(Appt this) { void setTime(Date this, long newTime) { Date thisDate = this.d; this.time = newTime; setTime(thisDate, 0); } } } }

  24. All constraints class Appt { private Date d; void setDate(Appt this , Date newDate) { this.d = newDate; } Date getDate(Appt this) { class Date { Date result = this.d; private long time; return result; } … void reset(Appt this) { void setTime(Date this , long newTime) { Date thisDate = this.d; this.time = newTime; setTime(thisDate, 0); } } } }

  25. Propagate mutability via graph reachability class Appt { private Date d; void setDate(Appt this , Date newDate) { this.d = newDate; } Date getDate(Appt this) { class Date { Date result = this.d; private long time; return result; } … void reset(Appt this) { void setTime(Date this , long newTime) { Date thisDate = this.d; this.time = newTime; setTime(thisDate, 0); } } } }

  26. Propagate mutability via graph reachability class Appt { private Date d; void setDate(Appt this , Date newDate) { this.d = newDate; } Date getDate(Appt this) { class Date { Date result = this.d; private long time; return result; } … void reset(Appt this) { void setTime(Date this , long newTime) { Date thisDate = this.d; this.time = newTime; setTime(thisDate, 0); } } } }

Download Presentation
Download Policy: The content available on the website is offered to you 'AS IS' for your personal information and use only. It cannot be commercialized, licensed, or distributed on other websites without prior consent from the author. To download a presentation, simply click this link. If you encounter any difficulties during the download process, it's possible that the publisher has removed the file from their server.

Recommend


More recommend