1 / 38

Observations on the Assured Evolution of Concurrent Java Programs

Observations on the Assured Evolution of Concurrent Java Programs. Aaron Greenhouse, CMU SEI T. J. Halloran, CMU SCS William L. Scherlis, CMU SCS. Example: java.util.logging.Logger. public class Logger { ... private Filter filter; /** ...

nailah
Download Presentation

Observations on the Assured Evolution of Concurrent Java Programs

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. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Observations onthe Assured Evolution ofConcurrent Java Programs Aaron Greenhouse, CMU SEI T. J. Halloran, CMU SCS William L. Scherlis, CMU SCS

  2. Example: java.util.logging.Logger public class Logger { ... private Filter filter; /** ... * @param newFilter a filter object (may be null) */ public void setFilter(Filter newFilter) ... { if (!anonymous) manager.checkAccess(); filter = newFilter; } public void log(LogRecord record) { ... synchronized (this) { if (filter != null && !filter.isLoggable(record)) return; } ... } ... } Aaron Greenhouse, CMU SEI

  3. Example: java.util.logging.Logger public class Logger { ... private Filter filter; /** ... * @param newFilter a filter object (may be null) */ public void setFilter(Filter newFilter) ... { if (!anonymous) manager.checkAccess(); filter = newFilter; } public void log(LogRecord record) { ... synchronized (this) { if (filter != null && !filter.isLoggable(record)) return; } ... } ... } Aaron Greenhouse, CMU SEI

  4. Example: java.util.logging.Logger public class Logger { ... private Filter filter; /** ... * @param newFilter a filter object (may be null) */ public void setFilter(Filter newFilter) ... { if (!anonymous) manager.checkAccess(); filter = newFilter; } public void log(LogRecord record) { ... synchronized (this) { if (filter != null && !filter.isLoggable(record)) return; } ... } ... } Aaron Greenhouse, CMU SEI

  5. Example: java.util.logging.Logger /** @lock LogLock is this protects filter */public class Logger { ... private Filter filter; /** ... * @param newFilter a filter object (may be null) */ public synchronized void setFilter(Filter newFilter)…{ if (!anonymous) manager.checkAccess(); filter = newFilter; } public void log(LogRecord record) { ... synchronized (this) { if (filter != null && !filter.isLoggable(record)) return; } ... } ... } Aaron Greenhouse, CMU SEI

  6. Concurrent Programming is Hard • Reasoning about concurrent programs • What is the design intent? • Is code consistent with the design intent? • Need answers to • Assure safety of program • Evolve program Aaron Greenhouse, CMU SEI

  7. What is the Design Intent? Programmers ask • What data is shared by multiple threads? • What locks are used to protect it? • Whose responsibility is it to acquire the lock? • Is this delegate object owned by its referring object? Aaron Greenhouse, CMU SEI

  8. What is the Design Intent? Programmers often use conventions • E.g., Objects protects themselves But intent can be more complex: • Lock also protects a delegate object • E.g., queue protects its underlying array • Certain methods expect caller to acquire lock • E.g., “transactional” call patterns • Call isEmpty() before getHead() • Not all fields require protection • E.g., single-threaded usage à la AWT Aaron Greenhouse, CMU SEI

  9. Where is the Design Intent? Recovering design intent is hard: • Intent has non-local manifestations: • Distributed across method implementations • Distributed across class and its clients • No way to explicitly denote intent • Not part of language Aaron Greenhouse, CMU SEI

  10. Is Code Consistent with Intent? • Infeasible to test: Non-determinism • Difficult to inspect: Non-locality • Traditional verification tools too painful • High “expression cost” • Uncertain scalability • Whole-program analysis • Where’s the whole program? • Composable static analysis + Models… Aaron Greenhouse, CMU SEI

  11. Models and attributes “Mechanical” properties(non-functional) “this lock protects these fields” “single-threaded constructor” “unaliased field” Models provide cut points Locking responsibility Effects Aliasing Consequences Steps towards scalability Composability via cut points Incrementality Models Analysis Program components Reduced expressiveness No representation invariants Tension: Power–Scalability Some analyses almost global Composable Analysis + Models Aaron Greenhouse, CMU SEI

  12. What’s Next… • Annotations and the Fluid Analysis Tool • Case study results • Refactorings for concurrency Aaron Greenhouse, CMU SEI

  13. The Fluid Eclipse Plug-in Eclipse IDE Fluid Tool View Aaron Greenhouse, CMU SEI

  14. The Fluid Eclipse Plug-in Aaron Greenhouse, CMU SEI

  15. Reporting Code–Model Consistency Tool assures annotated models No annotations  no assurance Three classes of results • Code–model consistency • Code–model inconsistency • Informative — Request for annotation Aaron Greenhouse, CMU SEI

  16. Code–Model Inconsistency • Code is wrong — bug in the program • E.g., missing lock acquisition • Model is incomplete — bug in model • E.g., need to add more annotations • Model is incorrect — bug in model • E.g., wrong lock associated with shared state • Analysis is conservative — limitation of tool • E.g., analysis looses track of lock • E.g., memory model trickery Aaron Greenhouse, CMU SEI

  17. Fluid Tool: Prior Work Annotation, analysis, and tool publications • ICSE ’98 • ECOOP ’99 • Software—Practice and Experience ’01 • ICSE ’02 • PASTE ’02 • Greenhouse Dissertation ‘03 • OOPSLA ’03 eclipse Tech eXchange http://www.fluid.cs.cmu.edu/ Aaron Greenhouse, CMU SEI

  18. Example: BoundedFIFO Circular queue used for inter-thread communication in Log4j. /**@lock BufLock is this protects Instance*/ public class BoundedFIFO { … LoggingEvent[] buf; int numElts = 0, first = 0, next = 0, size; public BoundedFIFO(int size) { … } /**@requiresLock BufLock*/ public LoggingEvent get() { … } /**@requiresLock BufLock*/ public void put(LoggingEvent o) { … } // etc. } Aaron Greenhouse, CMU SEI

  19. Example: BoundedFIFO Circular queue used for inter-thread communication in Log4j. /**@lock BufLock is this protects Instance*/ public class BoundedFIFO { … LoggingEvent[] buf; int numElts = 0, first = 0, next = 0, size; public BoundedFIFO(int size) { … } /**@requiresLock BufLock*/ public LoggingEvent get() { … } /**@requiresLock BufLock*/ public void put(LoggingEvent o) { … } // etc. } Instances use themselves as the lock Aaron Greenhouse, CMU SEI

  20. Example: BoundedFIFO Circular queue used for inter-thread communication in Log4j. /**@lock BufLock is this protects Instance*/ public class BoundedFIFO { … LoggingEvent[] buf; int numElts = 0, first = 0, next = 0, size; public BoundedFIFO(int size) { … } /**@requiresLock BufLock*/ public LoggingEvent get() { … } /**@requiresLock BufLock*/ public void put(LoggingEvent o) { … } // etc. } Clients must acquire lock before calling method Aaron Greenhouse, CMU SEI

  21. BoundedFIFO: Bad Callsite Aaron Greenhouse, CMU SEI

  22. BoundedFIFO: Owned Array (1) Aaron Greenhouse, CMU SEI

  23. BoundedFIFO: Owned Array (2) /**@lock BufLock is this protects Instance*/ public class BoundedFIFO { …/** @unshared * @aggregate [] into Instance */ LoggingEvent[] buf; // etc. } Aaron Greenhouse, CMU SEI

  24. BoundedFIFO: Constructor (1) Aaron Greenhouse, CMU SEI

  25. BoundedFIFO: Constructor (2) /**@lock BufLock is this protects Instance*/ public class BoundedFIFO { …/** @singleThreaded * @borrowed this */ public BoundedFIFO(int maxSize) { … } // etc. } Aaron Greenhouse, CMU SEI

  26. BoundedFIFO: Assured Aaron Greenhouse, CMU SEI

  27. Case Study: Util.Concurrent Aaron Greenhouse, CMU SEI

  28. Case Studies Aaron Greenhouse, CMU SEI

  29. Refactoring • Preconditions ensure transformation safety • [ How we got into analysis ] • Safe refactoring needs • Explicit models • Analysis of consistency • Refactorings that transform both code and model Aaron Greenhouse, CMU SEI

  30. Split Lock: Before Start with an assuredlocking model /** @lock RectLock is this protects Instance */ public class Rectangle { private int x, y; private int w, h; public synchronized void move(int newX, int newY) { x = newX; y = newY; } public synchronized void resize(int newW, int newH) { w = newW; h = newH; } public synchronized void reconfigure( int newX, int newY, int newW, int newH) { x = newX; y = newY; w = newW; h = newH; } // etc. } {x,y} {w,h} {x,y, w,h} If move() and resize() are invoked more frequently than reconfigure(), splitting the lock will allow more aggressive concurrency within the program. Aaron Greenhouse, CMU SEI

  31. Split Lock: After /** @region public Location * @lock LocationLock is this protects Location * @region public Dimension * @lock DimLock is dimLock protects Dimension */ public class Rectangle { private final Object dimLock = new Object(); /** @mapInto Location */ private int x, y; /** @mapInto Dimension */ private int w, h; public void move(int newX, int newY) { synchronized (this) { x = newX; y = newY; } } public void resize(int newW, int newH) { synchronized (dimLock) { w = newW; h = newH; } } public void reconfigure( int newX, int newY, int newW, int newH) { synchronized (this) { synchronized (dimLock) { x = newX; y = newY; w = newW; h = newH; } } } // etc. } Aaron Greenhouse, CMU SEI

  32. Split Lock Caveats • Subclasses • Lock order to prevent deadlock • Updating @requiresLock annotations • Allowable interleavings Aaron Greenhouse, CMU SEI

  33. Refactoring: Related Work • [Lea 2000] describes lock splitting as a design concept • Compiler optimizations that modify the scope of critical sections • Via escape analysis • [Blanchet ’99], [Bogda & Hoelzle ’99], [Choi, et al. ’99], [Whaley & Rinard ’99] • [Plevyak, Zhang & Chien ’95] • In automatically parallelized programs • [Diniz & Rinard ’96], [Diniz & Rinard ’97] Aaron Greenhouse, CMU SEI

  34. Concurrency is difficult Defies testing and inspection Non-locality non-determinism Complex code patterns Driven by performance Reverse engineering is painful Capture results as models/annotations How can we be principled? Avoid concurrency Capture models Use refactoring Introduce complexity in a systematic manner Consistency of code and model Bad news Finds bugs Good news Assures absence of useful categories of bugs Enables safe refactoring Achieving success in practice Scalability Incrementality Late adoption Low barrier to entry Conclusion http://www.fluid.cs.cmu.edu Aaron Greenhouse, CMU SEI

  35. Extra Slides Here Aaron Greenhouse, CMU SEI

  36. Split Lock (1) Decreases lock granularity by moving “down” the region hierarchy. Inputs • Lock annotation @lock L is M protects R • Lock names { Li } and references { Mi } to use as the locks for subregions { Rj} of R Aaron Greenhouse, CMU SEI

  37. Split Lock (2) • For each synchronized block that acquires L • Determine the regions { Rj } used within • Replace with nested synchronized blocks that acquire { Lj } • Remove original @lock annotation • Insert new annotations@lock Li is Mi protects Ri Aaron Greenhouse, CMU SEI

  38. Split Lock: Before /** @lock RectLock is this protects Instance * @region public Location * @region public Dimension */ public class Rectangle { /** @mapInto Location */ private int x, y; /** @mapInto Dimension */ private int w, h; public synchronized void move(int newX, int newY) { x = newX; y = newY; } public synchronized void resize(int newW, int newH) { w = newW; h = newH; } public synchronized void reconfigure( int newX, int newY, int newW, int newH) { x = newX; y = newY; w = newW; h = newH; } // etc. } Aaron Greenhouse, CMU SEI

More Related