a framework for implementing pluggable type systems chris andreae james noble victoria university of...
Post on 19-Dec-2015
242 Views
Preview:
TRANSCRIPT
A Framework for A Framework for ImplementingImplementing
Pluggable Type SystemsPluggable Type Systems
A Framework for A Framework for ImplementingImplementing
Pluggable Type SystemsPluggable Type Systems
Chris AndreaeChris AndreaeJames NobleJames Noble
Victoria UniversityVictoria University of of WellingtonWellington
Shane ArkusShane Arkus
Todd MillsteinTodd Millstein
University of University of CaliforniaCalifornia
OOPSLA 2006, Oregon, Portland
JavaCOP
2/26
Types are good…
• Type-checkers help the programmer• But, they don’t always help enough!
• Existing type systems are not always sufficient:– Non-null references– Read-only references– Confined types– Style checking– …
3/26
…But not all the time
• Type systems are not always relevant:– Particularly restrictive systems– Domain-specific or limited applicability– Conflicting type systems
• Too many systems exist to use at once:
@Nonnull @Readonly @Borrowed @LockedBy(“this”) @TransactionAttribute(MANDATORY) @ReadEffect(“foo”) @WriteEffect(“bar”) public String<Owner> fetchString(@Nonnull Integer<World> which){...
@Nonnull @Readonly @Borrowed @LockedBy(“this”) @TransactionAttribute(MANDATORY) @ReadEffect(“foo”) @WriteEffect(“bar”) public String<Owner> fetchString(@Nonnull Integer<World> which){...
4/26
Pluggable Types
• Bracha [2004] introduced “Pluggable Types” :– Type systems should be optional – No effect on the runtime semantics
• Type annotations not mandatory in syntax– Type systems should be pluggable
• Multiple type systems for different needs
• JAVACOP– Express these constraints– Check and enforce the constraints on programs
5/26
Running Example – motivation
• protection of access to variables, methods, classes is enabled
– No mechanism to ensure that references to protected object do not escape
• Security example
private Identity[] signers;public Identity[] getSigners() { return signers; }
private Identity[] signers;public Identity[] getSigners() { return signers; }
Returns a reference to the
actual array!
6/26
Confined types
confunconf
outside
X
prevents leaks of sensitive object references from outside a certain protection domain.
8/26
Confined Class Declaration
rule ConfinedClassDef(ClassDef c){
where(confined(c)){
require(!c.getSym().isPublic ()):
error(c, "Confined class may not be public");
}
rule ConfinedClassDef(ClassDef c){
where(confined(c)){
require(!c.getSym().isPublic ()):
error(c, "Confined class may not be public");
}
• Confined types can not be public
public @confined class C {
…
};
public @confined class C {
…
};
+
c.java:4: Confined class may not be public
public @confined class C ^1 error
9/26
JavaCOP System - Overview
javac compiler
Errors andWarnings
JavaCOP.Framework
JavaCOP.Compiler
JavaCOP Rules
Compiled constraints(Java class)
Compiled Program
JavaProgram
10/26
JavaCOP and Javac
javac compiler
Java program with
new types
ASTofthe
program
JavaCOPrules
11/26
AST Node types
Method call, like meth(args);
Instance creation, like new World(“Hello”);
Field or method selection, i.e., o.field or
o.method;()
+ type :Type+ pos :int
Tree
+ lhs :Tree+ rhs :Tree
AssignClassDef
MethodDef
+ selected :Tree+name
Select
+ meth :Tree+args
Apply
NewClass
…
12/26
JavaCOP Object Model
•An abstraction of javac AST
– Hides irrelevant structures– Augmented with typing and
information on program entities:•Type nodes •Symbol nodes•Env structs •Globals
+isPrimitive() : Boolean+restype() : Type+outer() : Type
Type
ClassType MethodType
-name-type : Type
Symbol
ClassSymbol VarSymbol MethodSymbol
…
13/26
The Rule Language • JavaCOP.Language source file is a set of
rules• Each rule
• applies to a particular kind of AST node• an advice on a static joinpoint in the AST
traversal program
• Has a set of constraints– If fail, error/warning is emitted
• Expressive language– Pattern matching, quantifiers, conditionals…
javac compiler
Errors andWarnings
JavaCOP.Framework
JavaCOP.Compiler
Compiled constraints
Compiled Program
JavaProgram
rules
declares
requirements
14/26
Conditional Constraints• If a method is public or protected and is
confined, it must be in a confined class
rule ConfinedMethodDef(MethodDef m){
where((m.isPublic() ||
m.isProtected()) &&
confined(m.type().restype)){
require(confined(m.enclClass())):
error(m, "Confined non private
method return type in
unconfined class”) }}
}
rule ConfinedMethodDef(MethodDef m){
where((m.isPublic() ||
m.isProtected()) &&
confined(m.type().restype)){
require(confined(m.enclClass())):
error(m, "Confined non private
method return type in
unconfined class”) }}
}
Condition
Failure clause
Primitive constraint
MethodDef node type
15/26
Pattern Matching rules
• Conditions on structural patterns.• Example – Anonymity preserving
– method calls with an (explicit or implicit) receiver of this are either to static methods or to other anonymous methods.
rule AnonCallsAnon(Apply a){
where(anonymous(env.enclMethod ){
where(a.meth => [this.*] || a.meth => [*]){
require(a.meth.isStatic || anonymous(a.meth)):
error(i, "’this ’ may not be used to "+
"call non -anonymous methods."); }}}
rule AnonCallsAnon(Apply a){
where(anonymous(env.enclMethod ){
where(a.meth => [this.*] || a.meth => [*]){
require(a.meth.isStatic || anonymous(a.meth)):
error(i, "’this ’ may not be used to "+
"call non -anonymous methods."); }}}
16/26
Quantification Rules
rule ConfinedClassDef2(ClassDef c){ where(confined(c)){ forall(Type s : c.supertypes ()){ require(confined(s) || s == globals.objectType): error(c, "A confined class may not extend " + "an unconfined superclass");}}}
rule ConfinedClassDef2(ClassDef c){ where(confined(c)){ forall(Type s : c.supertypes ()){ require(confined(s) || s == globals.objectType): error(c, "A confined class may not extend " + "an unconfined superclass");}}}
• Constrain properties of collection of objects– Lists, AST subtrees
• Similar to Java 5 enhanced for loop
• Example- confined class as extension– A confined class may not extend an unconfined type.
17/26
Subtype Rules• Subtyping is fundamental to Java’s type system
– Subtype Rules allow declaring subtyping relations
• Example- a value of confined type cannot be viewed at an unconfined supertype
• Applies to AST nodes change the type of an expression– Assignment, parameter passing, result returning, type casts.
• Passed: – type of the expression– supertype it must conform to– AST node where the test occurs
rule checkConfined(a <: b @ t){ where(confined(a)){ require(confined(b)): error(t, "Confined type "+a +" may not be treated as a subtype of" +"unconfined type "+b); }}
rule checkConfined(a <: b @ t){ where(confined(a)){ require(confined(b)): error(t, "Confined type "+a +" may not be treated as a subtype of" +"unconfined type "+b); }}
18/26
Predicates Declarations
• Describe complex properties without repeating.
– Readable– Reusable
• Invoked by the bodies of rules and other predicatesdeclare anonymous(Tree t){ require(t.holdsSymbol && t.sym.hasAnnotation("Anon"));}
declare anonymous(Tree t){ require(t.holdsSymbol && t.sym.hasAnnotation("Anon"));}
19/26
Disjunctive Constraints using Predicates
• Can have multiple predicates with same signature.
–Prolog like
• The predicate holds if any of its definitions hold• Example- definition of Confined
rule ConfinedClassDef(ClassDef c){ where(confined(c)){ require(!c.getSym().isPublic ()): error(c, "Confined class may not be public");
rule ConfinedClassDef(ClassDef c){ where(confined(c)){ require(!c.getSym().isPublic ()): error(c, "Confined class may not be public");
declare confined(Type t){ require(t.isArray()); require(confined(t.elemtype)); }
declare confined(Type t){ require(!t.isArray()); require(t.hasAnnotation("Confined")); }
declare confined(Type t){ require(!t.isArray()); exists(Type p : t.allparams()){ require(confined(p)); }}
declare confined(Type t){ require(t.isArray()); require(confined(t.elemtype)); }
declare confined(Type t){ require(!t.isArray()); require(t.hasAnnotation("Confined")); }
declare confined(Type t){ require(!t.isArray()); exists(Type p : t.allparams()){ require(confined(p)); }}
20/26
Failure Clauses• Three parts
–error/warning–Position in source–Message to report
• If a statement fails, JavaCOP searches for the nearest enclosing failure clause and executes it.
require(a){ require(b); require(c): error(pos1 , "error - c has failed");}: warning(globals.NOPOS , "warning - a or b have failed")
require(a){ require(b); require(c): error(pos1 , "error - c has failed");}: warning(globals.NOPOS , "warning - a or b have failed")
21/26
•Augmented Sun javac compiler
– Passes over each class after type checking
•Defines JavaCOP API methods– Can be used directly – Can serve as a base for high-level systems
•JavaCOP rule languagejavac compiler
Errors andWarnings
Parser ASTType Checking
AugmentedAST
JavaCOP.Framework
Rest of Compiler
JavaCOP.Compiler
JavaCOP Rules
Compiled constraints(Java class)
Compiled Program
JavaProgram
The JavaCop Framework
22/26
The JavaCOP Framework Implementation
• Checks source code, not byte code– More information available
•Generic types•Many annotations
• Compiles each .java file separately– Modular design, like javac– Extract interface information from bytecode
• Performance– Less than twice the compile time
• Insulates compiled rulesets from compiler implementation
– Port to other compilers without changing the language
• Implemented in Java
23/26
The JavaCOP Compiler
•Translates rules into java code – Source–level transformation
•New code – Extends interface exposed by Framework.– Compiled into bytecode using regular Java
compiler
•Implemented in Haskelljavac compiler
Errors andWarnings
JavaCOP.Framework
JavaCOP.Compiler Compiled constraints
Compiled Program
JavaProgram
JavaCOP Rules
Parse syntax tree
Generate Java source
24/26
Applications
Successfully implemented several existing systems:• Type systems:
– Confined Types [Vitek & Bokowski 1999]– Scoped Types for Real-Time Scoped Java [Zhao et al. 2004]– Race Condition Detection [Flanagan & Freund 2000]– Generic Ownership [Potanin et al. 2006]– Javari’s notion of reference immutability [Tschantz & Ernst 2005]
• Other program constraints:– An EJB3.0 verifier– Two rulesets from the PMD Java style checker– Identifying “Degenerate Class” micro-patterns [Gil & Maman 2005]– Collecting structural information for OO metrics [Chidamber & Kemerer
1991]
25/26
ContributionThe first practical framework for pluggable
types. • Rule Language for Pluggable Types
– Clear, expressive, easy to use
• Implementation– Integrated into standard development process– Rule language compiler
• Validation– Demonstrated on a range of type systems and other
constraints
• Useful for programmers– Choose type systems as needed
• Useful for researchers– Experiment easily with novel type systems
26/26
Limitations
JavaCOP doesn’t support:• Whole program analysis
– Integrated with Java’s modular compilation.
• Dynamic checks– Necessary for downcasts
• Flow sensitivity
top related