Date post: | 31-Dec-2015 |
Category: |
Documents |
Upload: | felicity-ruby-anderson |
View: | 217 times |
Download: | 1 times |
4 March 2004
Scoped Promises
Scaling up model expressionin the Fluid system
Tim HalloranSSSG
@promise “@borrows this” for new(**)
@assume “@useTypeWherePossible java
4 March 2004Scoped PromisesSSSG
This talk• Motivation
• Scoped promises– @promise– @assume
• Impact on tool architecture
• Related work
• Conclusions
4 March 2004Scoped PromisesSSSG
Motivation
• Problem 1: Annotation (tedious)– Anti-Example:
• Log4j’s DateFormatManager
– Last SSSG demo
• Chains of evidence…experience at scale:
• Problem 2: Team modeling (lack)– Anti-Example:
• Log4j’s BoundedFIFO
– OOPSLA demo (uniqueness assurance)
4 March 2004Scoped PromisesSSSG
public class DateFormatManager { private TimeZone _timeZone = null, Locale _locale = null; private String _pattern = null, DateFormat _dateFormat = null; public DateFormatManager() { super(); \underline~configure()^; } public DateFormatManager(TimeZone timeZone) {...} public DateFormatManager(Locale locale) {...} public DateFormatManager(String pattern) {...} public DateFormatManager(TimeZone timeZone, Locale locale) {...} public DateFormatManager(TimeZone timeZone, String pattern) {...} public DateFormatManager(Locale locale, String pattern) {...} public DateFormatManager(TimeZone timeZone, Locale locale, ...) {...} public synchronized TimeZone getTimeZone() {...} public synchronized void setTimeZone(TimeZone timeZone) {...} public synchronized Locale getLocale() {...} public synchronized void setLocale(Locale locale) {...} public synchronized String getPattern() {...} public synchronized void setPattern(String pattern) {...} public synchronized DateFormat getDateFormatInstance() {...} public synchronized void setDateFormatInstance(DateFormat ...) {...} public String format(Date date) {...} public String format(Date date, String pattern) {...} public Date parse(String date) throws ParseException {...} public Date parse(String date, String pattern) throws ... {...} private synchronized void configure() { _dateFormat = SimpleDateFormat.getDateTimeInstance( DateFormat.FULL, DateFormat.FULL, getLocale()); _dateFormat.setTimeZone(getTimeZone()); if (_pattern != null) ((SimpleDateFormat) _dateFormat).applyPattern(_pattern); }}
org.apache.log4j.lf5.util.
DateFormatManager
• Straightforward concurrency policy– synchronized
methods protect private fields
• 8 constructors• “getter” and
“setter” methods• A utility routine configure() to maintain state invariants
4 March 2004Scoped PromisesSSSG
/** @lock L is this protects Instance */public class DateFormatManager { private TimeZone _timeZone = null, Locale _locale = null; private String _pattern = null, DateFormat _dateFormat = null; public DateFormatManager() { super(); \underline~configure()^; } public DateFormatManager(TimeZone timeZone) {...} public DateFormatManager(Locale locale) {...} public DateFormatManager(String pattern) {...} public DateFormatManager(TimeZone timeZone, Locale locale) {...} public DateFormatManager(TimeZone timeZone, String pattern) {...} public DateFormatManager(Locale locale, String pattern) {...} public DateFormatManager(TimeZone timeZone, Locale locale, ...) {...} public synchronized TimeZone getTimeZone() {...} public synchronized void setTimeZone(TimeZone timeZone) {...} public synchronized Locale getLocale() {...} public synchronized void setLocale(Locale locale) {...} public synchronized String getPattern() {...} public synchronized void setPattern(String pattern) {...} public synchronized DateFormat getDateFormatInstance() {...} public synchronized void setDateFormatInstance(DateFormat ...) {...} public String format(Date date) {...} public String format(Date date, String pattern) {...} public Date parse(String date) throws ParseException {...} public Date parse(String date, String pattern) throws ... {...} private synchronized void configure() { _dateFormat = SimpleDateFormat.getDateTimeInstance( DateFormat.FULL, DateFormat.FULL, getLocale()); _dateFormat.setTimeZone(getTimeZone()); if (_pattern != null) ((SimpleDateFormat) _dateFormat).applyPattern(_pattern); }}
org.apache.log4j.lf5.util.
DateFormatManager
Step 1:Add the lock model
@lock L is this protects Instance
Declares that the object instance (this) is intended to protect all the object’s fields
4 March 2004Scoped PromisesSSSG
/** @lock L is this protects Instance */public class DateFormatManager { private TimeZone _timeZone = null, Locale _locale = null; private String _pattern = null, DateFormat _dateFormat = null; public DateFormatManager() { super(); \underline~configure()^; } public DateFormatManager(TimeZone timeZone) {...} public DateFormatManager(Locale locale) {...} public DateFormatManager(String pattern) {...} public DateFormatManager(TimeZone timeZone, Locale locale) {...} public DateFormatManager(TimeZone timeZone, String pattern) {...} public DateFormatManager(Locale locale, String pattern) {...} public DateFormatManager(TimeZone timeZone, Locale locale, ...) {...} public synchronized TimeZone getTimeZone() {...} public synchronized void setTimeZone(TimeZone timeZone) {...} public synchronized Locale getLocale() {...} public synchronized void setLocale(Locale locale) {...} public synchronized String getPattern() {...} public synchronized void setPattern(String pattern) {...} public synchronized DateFormat getDateFormatInstance() {...} public synchronized void setDateFormatInstance(DateFormat ...) {...} public String format(Date date) {...} public String format(Date date, String pattern) {...} public Date parse(String date) throws ParseException {...} public Date parse(String date, String pattern) throws ... {...} private synchronized void configure() { _dateFormat = SimpleDateFormat.getDateTimeInstance( DateFormat.FULL, DateFormat.FULL, getLocale()); _dateFormat.setTimeZone(getTimeZone()); if (_pattern != null) ((SimpleDateFormat) _dateFormat).applyPattern(_pattern); }}
org.apache.log4j.lf5.util.
DateFormatManager
4 March 2004Scoped PromisesSSSG
/** @lock L is this protects Instance */public class DateFormatManager { private TimeZone _timeZone = null, Locale _locale = null; private String _pattern = null, DateFormat _dateFormat = null; /** @synchronized @borrowed this */ public DateFormatManager() { super(); \underline~configure()^; } /** @synchronized @borrowed this */ public DateFormatManager(TimeZone timeZone) {...} /** @synchronized @borrowed this */ public DateFormatManager(Locale locale) {...} /** @synchronized @borrowed this */ public DateFormatManager(String pattern) {...} /** @synchronized @borrowed this */ public DateFormatManager(TimeZone timeZone, Locale locale) {...} /** @synchronized @borrowed this */ public DateFormatManager(TimeZone timeZone, String pattern) {...} /** @synchronized @borrowed this */ public DateFormatManager(Locale locale, String pattern) {...} /** @synchronized @borrowed this */ public DateFormatManager(TimeZone timeZone, Locale locale, ...) {...} public synchronized TimeZone getTimeZone() {...} public synchronized void setTimeZone(TimeZone timeZone) {...} public synchronized Locale getLocale() {...} public synchronized void setLocale(Locale locale) {...} public synchronized String getPattern() {...} public synchronized void setPattern(String pattern) {...} public synchronized DateFormat getDateFormatInstance() {...} public synchronized void setDateFormatInstance(DateFormat ...) {...} public String format(Date date) {...} public String format(Date date, String pattern) {...} public Date parse(String date) throws ParseException {...} public Date parse(String date, String pattern) throws ... {...} private synchronized void configure() { _dateFormat = SimpleDateFormat.getDateTimeInstance( DateFormat.FULL, DateFormat.FULL, getLocale()); _dateFormat.setTimeZone(getTimeZone()); if (_pattern != null) ((SimpleDateFormat) _dateFormat).applyPattern(_pattern); }}
org.apache.log4j.lf5.util.
DateFormatManager
Step 2:Annotate theconstructors
@synchronized @borrowed this
Constructors behave “like” a synchronized method (they do not leak aliases)
4 March 2004Scoped PromisesSSSG
/** @lock L is this protects Instance */public class DateFormatManager { private TimeZone _timeZone = null, Locale _locale = null; private String _pattern = null, DateFormat _dateFormat = null; /** @synchronized @borrowed this */ public DateFormatManager() { super(); \underline~configure()^; } /** @synchronized @borrowed this */ public DateFormatManager(TimeZone timeZone) {...} /** @synchronized @borrowed this */ public DateFormatManager(Locale locale) {...} /** @synchronized @borrowed this */ public DateFormatManager(String pattern) {...} /** @synchronized @borrowed this */ public DateFormatManager(TimeZone timeZone, Locale locale) {...} /** @synchronized @borrowed this */ public DateFormatManager(TimeZone timeZone, String pattern) {...} /** @synchronized @borrowed this */ public DateFormatManager(Locale locale, String pattern) {...} /** @synchronized @borrowed this */ public DateFormatManager(TimeZone timeZone, Locale locale, ...) {...} public synchronized TimeZone getTimeZone() {...} public synchronized void setTimeZone(TimeZone timeZone) {...} public synchronized Locale getLocale() {...} public synchronized void setLocale(Locale locale) {...} public synchronized String getPattern() {...} public synchronized void setPattern(String pattern) {...} public synchronized DateFormat getDateFormatInstance() {...} public synchronized void setDateFormatInstance(DateFormat ...) {...} public String format(Date date) {...} public String format(Date date, String pattern) {...} public Date parse(String date) throws ParseException {...} public Date parse(String date, String pattern) throws ... {...} private synchronized void configure() { _dateFormat = SimpleDateFormat.getDateTimeInstance( DateFormat.FULL, DateFormat.FULL, getLocale()); _dateFormat.setTimeZone(getTimeZone()); if (_pattern != null) ((SimpleDateFormat) _dateFormat).applyPattern(_pattern); }}
org.apache.log4j.lf5.util.
DateFormatManager
4 March 2004Scoped PromisesSSSG
/** @lock L is this protects Instance */public class DateFormatManager { private TimeZone _timeZone = null, Locale _locale = null; private String _pattern = null, DateFormat _dateFormat = null; /** @synchronized @borrowed this */ public DateFormatManager() { super(); \underline~configure()^; } /** @synchronized @borrowed this */ public DateFormatManager(TimeZone timeZone) {...} /** @synchronized @borrowed this */ public DateFormatManager(Locale locale) {...} /** @synchronized @borrowed this */ public DateFormatManager(String pattern) {...} /** @synchronized @borrowed this */ public DateFormatManager(TimeZone timeZone, Locale locale) {...} /** @synchronized @borrowed this */ public DateFormatManager(TimeZone timeZone, String pattern) {...} /** @synchronized @borrowed this */ public DateFormatManager(Locale locale, String pattern) {...} /** @synchronized @borrowed this */ public DateFormatManager(TimeZone timeZone, Locale locale, ...) {...} public synchronized TimeZone getTimeZone() {...} public synchronized void setTimeZone(TimeZone timeZone) {...} public synchronized Locale getLocale() {...} public synchronized void setLocale(Locale locale) {...} public synchronized String getPattern() {...} public synchronized void setPattern(String pattern) {...} public synchronized DateFormat getDateFormatInstance() {...} public synchronized void setDateFormatInstance(DateFormat ...) {...} public String format(Date date) {...} public String format(Date date, String pattern) {...} public Date parse(String date) throws ParseException {...} public Date parse(String date, String pattern) throws ... {...} /** @borrowed this */ private synchronized void configure() { _dateFormat = SimpleDateFormat.getDateTimeInstance( DateFormat.FULL, DateFormat.FULL, getLocale()); _dateFormat.setTimeZone(getTimeZone()); if (_pattern != null) ((SimpleDateFormat) _dateFormat).applyPattern(_pattern); }}
org.apache.log4j.lf5.util.
DateFormatManager
Step 3:Annotateconfigure()
@borrowed thisThe method will not create an alias of this
4 March 2004Scoped PromisesSSSG
/** @lock L is this protects Instance */public class DateFormatManager { private TimeZone _timeZone = null, Locale _locale = null; private String _pattern = null, DateFormat _dateFormat = null; /** @synchronized @borrowed this */ public DateFormatManager() { super(); \underline~configure()^; } /** @synchronized @borrowed this */ public DateFormatManager(TimeZone timeZone) {...} /** @synchronized @borrowed this */ public DateFormatManager(Locale locale) {...} /** @synchronized @borrowed this */ public DateFormatManager(String pattern) {...} /** @synchronized @borrowed this */ public DateFormatManager(TimeZone timeZone, Locale locale) {...} /** @synchronized @borrowed this */ public DateFormatManager(TimeZone timeZone, String pattern) {...} /** @synchronized @borrowed this */ public DateFormatManager(Locale locale, String pattern) {...} /** @synchronized @borrowed this */ public DateFormatManager(TimeZone timeZone, Locale locale, ...) {...} public synchronized TimeZone getTimeZone() {...} public synchronized void setTimeZone(TimeZone timeZone) {...} public synchronized Locale getLocale() {...} public synchronized void setLocale(Locale locale) {...} public synchronized String getPattern() {...} public synchronized void setPattern(String pattern) {...} public synchronized DateFormat getDateFormatInstance() {...} public synchronized void setDateFormatInstance(DateFormat ...) {...} public String format(Date date) {...} public String format(Date date, String pattern) {...} public Date parse(String date) throws ParseException {...} public Date parse(String date, String pattern) throws ... {...} /** @borrowed this */ private synchronized void configure() { _dateFormat = SimpleDateFormat.getDateTimeInstance( DateFormat.FULL, DateFormat.FULL, getLocale()); _dateFormat.setTimeZone(getTimeZone()); if (_pattern != null) ((SimpleDateFormat) _dateFormat).applyPattern(_pattern); }}
org.apache.log4j.lf5.util.
DateFormatManager
4 March 2004Scoped PromisesSSSG
/** @lock L is this protects Instance */public class DateFormatManager { private TimeZone _timeZone = null, Locale _locale = null; private String _pattern = null, DateFormat _dateFormat = null; /** @synchronized @borrowed this */ public DateFormatManager() { super(); \underline~configure()^; } /** @synchronized @borrowed this */ public DateFormatManager(TimeZone timeZone) {...} /** @synchronized @borrowed this */ public DateFormatManager(Locale locale) {...} /** @synchronized @borrowed this */ public DateFormatManager(String pattern) {...} /** @synchronized @borrowed this */ public DateFormatManager(TimeZone timeZone, Locale locale) {...} /** @synchronized @borrowed this */ public DateFormatManager(TimeZone timeZone, String pattern) {...} /** @synchronized @borrowed this */ public DateFormatManager(Locale locale, String pattern) {...} /** @synchronized @borrowed this */ public DateFormatManager(TimeZone timeZone, Locale locale, ...) {...} public synchronized TimeZone getTimeZone() {...} public synchronized void setTimeZone(TimeZone timeZone) {...} /** @borrowed this */ public synchronized Locale getLocale() {...} public synchronized void setLocale(Locale locale) {...} public synchronized String getPattern() {...} public synchronized void setPattern(String pattern) {...} public synchronized DateFormat getDateFormatInstance() {...} public synchronized void setDateFormatInstance(DateFormat ...) {...} public String format(Date date) {...} public String format(Date date, String pattern) {...} public Date parse(String date) throws ParseException {...} public Date parse(String date, String pattern) throws ... {...} /** @borrowed this */ private synchronized void configure() { _dateFormat = SimpleDateFormat.getDateTimeInstance( DateFormat.FULL, DateFormat.FULL, getLocale()); _dateFormat.setTimeZone(getTimeZone()); if (_pattern != null) ((SimpleDateFormat) _dateFormat).applyPattern(_pattern); }}
org.apache.log4j.lf5.util.
DateFormatManager
Step 3:AnnotategetLocale()
@borrowed this@borrowed thisThe method will not create an alias of this
4 March 2004Scoped PromisesSSSG
/** @lock L is this protects Instance */public class DateFormatManager { private TimeZone _timeZone = null, Locale _locale = null; private String _pattern = null, DateFormat _dateFormat = null; /** @synchronized @borrowed this */ public DateFormatManager() { super(); \underline~configure()^; } /** @synchronized @borrowed this */ public DateFormatManager(TimeZone timeZone) {...} /** @synchronized @borrowed this */ public DateFormatManager(Locale locale) {...} /** @synchronized @borrowed this */ public DateFormatManager(String pattern) {...} /** @synchronized @borrowed this */ public DateFormatManager(TimeZone timeZone, Locale locale) {...} /** @synchronized @borrowed this */ public DateFormatManager(TimeZone timeZone, String pattern) {...} /** @synchronized @borrowed this */ public DateFormatManager(Locale locale, String pattern) {...} /** @synchronized @borrowed this */ public DateFormatManager(TimeZone timeZone, Locale locale, ...) {...} public synchronized TimeZone getTimeZone() {...} public synchronized void setTimeZone(TimeZone timeZone) {...} /** @borrowed this */ public synchronized Locale getLocale() {...} public synchronized void setLocale(Locale locale) {...} public synchronized String getPattern() {...} public synchronized void setPattern(String pattern) {...} public synchronized DateFormat getDateFormatInstance() {...} public synchronized void setDateFormatInstance(DateFormat ...) {...} public String format(Date date) {...} public String format(Date date, String pattern) {...} public Date parse(String date) throws ParseException {...} public Date parse(String date, String pattern) throws ... {...} /** @borrowed this */ private synchronized void configure() { _dateFormat = SimpleDateFormat.getDateTimeInstance( DateFormat.FULL, DateFormat.FULL, getLocale()); _dateFormat.setTimeZone(getTimeZone()); if (_pattern != null) ((SimpleDateFormat) _dateFormat).applyPattern(_pattern); }}
org.apache.log4j.lf5.util.
DateFormatManager
4 March 2004Scoped PromisesSSSG
/** @lock L is this protects Instance */public class DateFormatManager { private TimeZone _timeZone = null, Locale _locale = null; private String _pattern = null, DateFormat _dateFormat = null; /** @synchronized @borrowed this */ public DateFormatManager() { super(); \underline~configure()^; } /** @synchronized @borrowed this */ public DateFormatManager(TimeZone timeZone) {...} /** @synchronized @borrowed this */ public DateFormatManager(Locale locale) {...} /** @synchronized @borrowed this */ public DateFormatManager(String pattern) {...} /** @synchronized @borrowed this */ public DateFormatManager(TimeZone timeZone, Locale locale) {...} /** @synchronized @borrowed this */ public DateFormatManager(TimeZone timeZone, String pattern) {...} /** @synchronized @borrowed this */ public DateFormatManager(Locale locale, String pattern) {...} /** @synchronized @borrowed this */ public DateFormatManager(TimeZone timeZone, Locale locale, ...) {...} /** @borrowed this */ public synchronized TimeZone getTimeZone() {...} public synchronized void setTimeZone(TimeZone timeZone) {...} /** @borrowed this */ public synchronized Locale getLocale() {...} public synchronized void setLocale(Locale locale) {...} public synchronized String getPattern() {...} public synchronized void setPattern(String pattern) {...} public synchronized DateFormat getDateFormatInstance() {...} public synchronized void setDateFormatInstance(DateFormat ...) {...} public String format(Date date) {...} public String format(Date date, String pattern) {...} public Date parse(String date) throws ParseException {...} public Date parse(String date, String pattern) throws ... {...} /** @borrowed this */ private synchronized void configure() { _dateFormat = SimpleDateFormat.getDateTimeInstance( DateFormat.FULL, DateFormat.FULL, getLocale()); _dateFormat.setTimeZone(getTimeZone()); if (_pattern != null) ((SimpleDateFormat) _dateFormat).applyPattern(_pattern); }}
org.apache.log4j.lf5.util.
DateFormatManager
Step 3:AnnotategetTimeZone()
@borrowed thisThe method will not create an alias of this
4 March 2004Scoped PromisesSSSG
/** @lock L is this protects Instance */public class DateFormatManager { private TimeZone _timeZone = null, Locale _locale = null; private String _pattern = null, DateFormat _dateFormat = null; /** @synchronized @borrowed this */ public DateFormatManager() { super(); \underline~configure()^; } /** @synchronized @borrowed this */ public DateFormatManager(TimeZone timeZone) {...} /** @synchronized @borrowed this */ public DateFormatManager(Locale locale) {...} /** @synchronized @borrowed this */ public DateFormatManager(String pattern) {...} /** @synchronized @borrowed this */ public DateFormatManager(TimeZone timeZone, Locale locale) {...} /** @synchronized @borrowed this */ public DateFormatManager(TimeZone timeZone, String pattern) {...} /** @synchronized @borrowed this */ public DateFormatManager(Locale locale, String pattern) {...} /** @synchronized @borrowed this */ public DateFormatManager(TimeZone timeZone, Locale locale, ...) {...} /** @borrowed this */ public synchronized TimeZone getTimeZone() {...} public synchronized void setTimeZone(TimeZone timeZone) {...} /** @borrowed this */ public synchronized Locale getLocale() {...} public synchronized void setLocale(Locale locale) {...} public synchronized String getPattern() {...} public synchronized void setPattern(String pattern) {...} public synchronized DateFormat getDateFormatInstance() {...} public synchronized void setDateFormatInstance(DateFormat ...) {...} public String format(Date date) {...} public String format(Date date, String pattern) {...} public Date parse(String date) throws ParseException {...} public Date parse(String date, String pattern) throws ... {...} /** @borrowed this */ private synchronized void configure() { _dateFormat = SimpleDateFormat.getDateTimeInstance( DateFormat.FULL, DateFormat.FULL, getLocale()); _dateFormat.setTimeZone(getTimeZone()); if (_pattern != null) ((SimpleDateFormat) _dateFormat).applyPattern(_pattern); }}
org.apache.log4j.lf5.util.
DateFormatManager
Success!
That is, if the user didn’t already wipe our tool from the hard disk
4 March 2004Scoped PromisesSSSG
What is the bigger problem?
Annotation tedium is a symptom…• Problem: Chains of evidence is
incremental– “safe defaults” — correct Java is never wrong– Promises define precise models
• Cut-points on Java module interfaces to allow modular program analysis for assurance of model-code consistency
– User is faced with tedious promise expression
• Our Solution: @promise (+ tools)– Redo DateFormatManager demo
4 March 2004Scoped PromisesSSSG
/** @lock L is this protects Instance * @promise “@snychronized” for new(**)public class DateFormatManager { private TimeZone _timeZone = null, Locale _locale = null; private String _pattern = null, DateFormat _dateFormat = null; public DateFormatManager() { super(); \underline~configure()^; } public DateFormatManager(TimeZone timeZone) {...} public DateFormatManager(Locale locale) {...} public DateFormatManager(String pattern) {...} public DateFormatManager(TimeZone timeZone, Locale locale) {...} public DateFormatManager(TimeZone timeZone, String pattern) {...} public DateFormatManager(Locale locale, String pattern) {...} public DateFormatManager(TimeZone timeZone, Locale locale, ...) {...} public synchronized TimeZone getTimeZone() {...} public synchronized void setTimeZone(TimeZone timeZone) {...} public synchronized Locale getLocale() {...} public synchronized void setLocale(Locale locale) {...} public synchronized String getPattern() {...} public synchronized void setPattern(String pattern) {...} public synchronized DateFormat getDateFormatInstance() {...} public synchronized void setDateFormatInstance(DateFormat ...) {...} public String format(Date date) {...} public String format(Date date, String pattern) {...} public Date parse(String date) throws ParseException {...} public Date parse(String date, String pattern) throws ... {...} private synchronized void configure() { _dateFormat = SimpleDateFormat.getDateTimeInstance( DateFormat.FULL, DateFormat.FULL, getLocale()); _dateFormat.setTimeZone(getTimeZone()); if (_pattern != null) ((SimpleDateFormat) _dateFormat).applyPattern(_pattern); }}
@promise• Creates virtual
promises on all constructors
• @promise acts as a mechanism to place model promises on targeted declarations
• Better captures intent that should apply to “all” declarations– Changes the default
/** @lock L is this protects Instance * @promise “@snychronized” for new(**)public class DateFormatManager { private TimeZone _timeZone = null, Locale _locale = null; private String _pattern = null, DateFormat _dateFormat = null; /** @synchronized */ public DateFormatManager() { super(); \underline~configure()^; } /** @synchronized */ public DateFormatManager(TimeZone timeZone) {...} /** @synchronized */ public DateFormatManager(Locale locale) {...} /** @synchronized */ public DateFormatManager(String pattern) {...} /** @synchronized */ public DateFormatManager(TimeZone timeZone, Locale locale) {...} /** @synchronized */ public DateFormatManager(TimeZone timeZone, String pattern) {...} /** @synchronized */ public DateFormatManager(Locale locale, String pattern) {...} /** @synchronized */ public DateFormatManager(TimeZone timeZone, Locale locale, ...) {...} public synchronized TimeZone getTimeZone() {...} public synchronized void setTimeZone(TimeZone timeZone) {...} public synchronized Locale getLocale() {...} public synchronized void setLocale(Locale locale) {...} public synchronized String getPattern() {...} public synchronized void setPattern(String pattern) {...} public synchronized DateFormat getDateFormatInstance() {...} public synchronized void setDateFormatInstance(DateFormat ...) {...} public String format(Date date) {...} public String format(Date date, String pattern) {...} public Date parse(String date) throws ParseException {...} public Date parse(String date, String pattern) throws ... {...} private synchronized void configure() { _dateFormat = SimpleDateFormat.getDateTimeInstance( DateFormat.FULL, DateFormat.FULL, getLocale()); _dateFormat.setTimeZone(getTimeZone()); if (_pattern != null) ((SimpleDateFormat) _dateFormat).applyPattern(_pattern); }}
4 March 2004Scoped PromisesSSSG
Target pattern examplesPattern Example Description
Types * All top level types (type declarations)
edu.cmu.**:* All top level types in any sub-package of “edu.cmu”
edu.cmu.**:* All types in any sub-package of “edu.cmu”
constructors
new(**) All constructors (in any type)
Foo:new() All no-argument constructors in “Foo”
methods *(int, **) All methods (in any type) with an “int” first arg
int Foo:*(*) All methods returning “int” in “Foo” with one arg
!private *() All non-private methods with no arguments
fields List * All fields (in any type) of type list
“|” “&” and “!” create expressions: “new(**) | *(**)” “new(**) & !(new())”
4 March 2004Scoped PromisesSSSG
Scope of @promise• Target patterns are limited, in static
scope, by where the @promise appears– Type declaration Javadoc: That type
• I.e., target only pattern matches within the static scope of the type declaration
– JSR-175 “package.java”: That pkg and sub-pkgs
• Target pattern matches within all compilation units within that package and all sub-packages.
“Luke, there is another location for scoped promises”
4 March 2004Scoped PromisesSSSG
JSR-175 @promise example:non-null array return values
• From my proposal (null value assurance):
• Josh Bloch: no method returning an array reference should ever return null– @promise can do this: (in
/org/netbeans/package.java)
package org.netbeans.modules.debugger;public interface CallStackProducer extends CallStackRoot { ... public /*@not-null*/ Location[] getCallStack(); ...}
package org.netbeans;/** @promise “@return not-null” for *[+] *(**) */
4 March 2004Scoped PromisesSSSG
The 2nd (bigger) problem…
• Problem 2: Team modeling (lack)– Anti-Example:
• Log4j’s BoundedFIFO• OOPSLA demo
4 March 2004Scoped PromisesSSSG
Trouble with BoundedFIFO
• When uniqueness assurance (Boyland) was “turned-on” BoundedFIFO could not be be assured
– A call to java.lang.System.arraycopy() was made passing an unshared field as the data source
– Uniqueness assurance wants arraycopy() to promise that its first parameter is “borrowed”
org.apache.log4j.helpers.
BoundedFIFO
4 March 2004Scoped PromisesSSSG
The offending source code
/** * @lock BufLock is this protects Instance * @promise "@borrowed this" for new(**) | *(**) * @promise "@synchronized" for new(**) * @promise "@requiresLock BufLock" for *(**) & !(resize(**)) */public class BoundedFIFO { /** @unshared @aggregate [] into Instance */ LoggingEvent[] buf; ... synchronized public void resize(int newSize) { ... System.arraycopy(buf, first, tmp, 0, len1); ... }}
org.apache.log4j.helpers.
BoundedFIFO
4 March 2004Scoped PromisesSSSG
Our current tool solution
• We avoid direct annotation of library code via a scheme called an XML promise
• The XML promise for arraycopy():
org.apache.log4j.helpers.
BoundedFIFO
4 March 2004Scoped PromisesSSSG
org.apache.log4j.helpers.
BoundedFIFO
That is, if the user didn’t already wipe our tool from the hard disk
Success!/** * @lock BufLock is this protects Instance * @promise "@borrowed this" for new(**) | *(**) * @promise "@synchronized" for new(**) * @promise "@requiresLock BufLock" for *(**) & !(resize(**)) */public class BoundedFIFO { /** @unshared @aggregate [] into Instance */ LoggingEvent[] buf; ... synchronized public void resize(int newSize) { ... System.arraycopy(buf, first, tmp, 0, len1); ... }}
4 March 2004Scoped PromisesSSSG
What is the bigger problem?
Library annotation is a symptom…• Problem: Chains of evidence is
modular and relies upon interface specification– User is faced with modeling design intent in
unfamiliar parts of a software system– We have no scheme to enable modeling by
a team of developers
• Our Solution: @assume (+ tools)@assume has been controversial (even among the “extended” Fluid team)
4 March 2004Scoped PromisesSSSG
Fixing BoundedFIFO
/** * @lock BufLock is this protects Instance * @promise "@borrowed this" for new(**) | *(**) * @promise "@synchronized" for new(**) * @promise "@requiresLock BufLock" for *(**) & !(resize(**)) * @assume “@borrowed arg0” * for “System.arraycopy(Object, int, Object, int, int)” */public class BoundedFIFO { /** @unshared @aggregate [] into Instance */ LoggingEvent[] buf; ... synchronized public void resize(int newSize) { ... System.arraycopy(buf, first, tmp, 0, len1); ... }}
org.apache.log4j.helpers.
BoundedFIFO
(aside) Apache Bug 26224
4 March 2004Scoped PromisesSSSG
@assume• Answers: If a model existed in
(unfamiliar) code is my code consistent with this model?
• Allows local expression of non-local models– Avoiding programmer modeling of unfamiliar
code but precisely capturing assumptions about the rest of the system
– Tool creates a highly-focused TODO list of assumed properties for action by other programmers java.lang.System: arraycopy() assumed “@borrowed arg0”
Assurance Help Wanted Board: (1 item)
4 March 2004Scoped PromisesSSSG
Scope of @assume• Promise visibility is limited, in static
scope, by where the @assume appears– Type declaration Javadoc: That type
• I.e., You only “see” the promise assumed within the type however, the promise target is not restricted
– JSR-175 “package.java”: That pkg and sub-pkgs
• Promise is visible within all compilation units within that package and all sub-packages. Again, the promise target is not restricted
4 March 2004Scoped PromisesSSSG
@assume: Enforcing a standard
• Consider, a type use advice assurance:
• This is not useful in practice– It is not followed universally
• 1,374 violations (for ArrayList and LinkedList) found in the J2SDK, Ant, Tomcat, Eclipse, NetBeans (Halloran)
– The promise is idiosyncratic (? Collection)
• Use of @assume (JSR-175) makes this useful
package java.util;/** @useTypeWherePossible java.util.List */class ArrayList extends AbstractList implements List, RandomAccess, ... {...}
package edu.cs.cmu.fluid;/** @assume “@useTypeWherePossible java.util.List” for “java.util.List+” */
4 March 2004Scoped PromisesSSSG
Impact on tool architecture• @promise and @assume are, by design, (mostly)
transparent to analysis code:– All bindings must provide “from” AST location– All links to promises a result depends upon must be
reported
• @promise creates virtual promises in the AST
• @assume “makes” virtual promises visible only within its static scope (defined by annotation location)– Tacit assumption: analyses are not whole-program
• “if you give @assume semantics over *both* the scope of the promise *and* the scope of the analysis that checks uses, then you will get the (secondary) unsoundness for a non-modular analysis” (Boyland) – concrete example next slide…
4 March 2004Scoped PromisesSSSG
Broke @assume example(whole-program @useTypeWherePossible)
• Analysis result: stuff should be declared of type List– Change results in compiler error due to use in Sneaky
• Problem: Analysis that checks uses is whole-program• Solution: Make modular (limit to private fields & local
variables) or forbid use of the promise in an @assume
/** @assume “@useTypeWherePossible java.util.List” for “java.util.ArrayList” */class Nice { static public ArrayList stuff = new ArrayList(); public void add(Object o) { stuff.add(o); }}
class Sneaky { public void m() { Nice.stuff.ensureCapacity(1000); }}
4 March 2004Scoped PromisesSSSG
Related work• Promises (Chan, Boyland, Scherlis)
• Aspect Oriented Programming– Loosely: promise≈advice / target≈pointcut– AspectJ (Kiczales, Lamping, Mendhekar, et al.)– Statically executable advice (Lieberherr, et al.)
• JML (Leavens, et al.)– @refine composition focused (Larch traits)– @assume caller obligation (@requiresLock)
• ESC/Java (Leino, Nelson, et al.)• Modular but model expression is not incremental• @assume @axiom Trusted direction to theorem prover
• Programming languages/Specification languages (ideas)
4 March 2004Scoped PromisesSSSG
Conclusion• Presented two scoped promises
– @promise: avoiding tedious annotation (cut-paste)– @assume: supporting modeling by a team of developers
• Concrete solutions toward making chains of evidence practical for developers and teams of developers
• A general mechanism available to current and future chains of evidence assurances– Transparent to their implementation– Avoids ad hoc per-assurance solutions