A Framework for Implementing Pluggable Type Systems

25
A Framework for A Framework for Implementing Implementing Pluggable Type Systems Pluggable Type Systems Chris Andreae Chris Andreae James Noble James Noble Victoria University Victoria University of Wellington of Wellington Shane Arkus Shane Arkus Todd Todd Millstein Millstein University of University of California California OOPSLA 2006, Oregon, Portland JavaCOP

description

JavaCOP. A Framework for Implementing Pluggable Type Systems. Shane Arkus Todd Millstein University of California. Chris Andreae James Noble Victoria University of Wellington. OOPSLA 2006, Oregon, Portland. Types are good …. Type-checkers help the programmer - PowerPoint PPT Presentation

Transcript of A Framework for Implementing Pluggable Type Systems

Page 1: A Framework for Implementing Pluggable Type Systems

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

Page 2: A Framework for Implementing Pluggable Type Systems

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– …

Page 3: A Framework for Implementing Pluggable Type Systems

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){...

Page 4: A Framework for Implementing Pluggable Type Systems

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

Page 5: A Framework for Implementing Pluggable Type Systems

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!

Page 6: A Framework for Implementing Pluggable Type Systems

6/26

Confined types

confunconf

outside

X

prevents leaks of sensitive object references from outside a certain protection domain.

Page 7: A Framework for Implementing Pluggable Type Systems

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

Page 8: A Framework for Implementing Pluggable Type Systems

9/26

JavaCOP System - Overview

javac compiler

Errors andWarnings

JavaCOP.Framework

JavaCOP.Compiler

JavaCOP Rules

Compiled constraints(Java class)

Compiled Program

JavaProgram

Page 9: A Framework for Implementing Pluggable Type Systems

10/26

JavaCOP and Javac

javac compiler

Java program with

new types

ASTofthe

program

JavaCOPrules

Page 10: A Framework for Implementing Pluggable Type Systems

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

Page 11: A Framework for Implementing Pluggable Type Systems

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

Page 12: A Framework for Implementing Pluggable Type Systems

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

Page 13: A Framework for Implementing Pluggable Type Systems

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

Page 14: A Framework for Implementing Pluggable Type Systems

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."); }}}

Page 15: A Framework for Implementing Pluggable Type Systems

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.

Page 16: A Framework for Implementing Pluggable Type Systems

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); }}

Page 17: A Framework for Implementing Pluggable Type Systems

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"));}

Page 18: A Framework for Implementing Pluggable Type Systems

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)); }}

Page 19: A Framework for Implementing Pluggable Type Systems

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")

Page 20: A Framework for Implementing Pluggable Type Systems

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

Page 21: A Framework for Implementing Pluggable Type Systems

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

Page 22: A Framework for Implementing Pluggable Type Systems

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

Page 23: A Framework for Implementing Pluggable Type Systems

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]

Page 24: A Framework for Implementing Pluggable Type Systems

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

Page 25: A Framework for Implementing Pluggable 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