1 practical pluggable types for java chris andreae james noble victoria university of wellington...

26
1 Practical Pluggable types for Java Chris Andreae James Noble Victoria University of Wellington Shane Arkus Todd Millstein University of California Presented by Lina Zarivach

Upload: aja-dingley

Post on 02-Apr-2015

217 views

Category:

Documents


1 download

TRANSCRIPT

Page 1: 1 Practical Pluggable types for Java Chris Andreae James Noble Victoria University of Wellington Shane Arkus Todd Millstein University of California Presented

1

Practical Pluggable types for Java

Chris Andreae

James Noble

Victoria University of Wellington

Shane Arkus

Todd Millstein

University of California

Presented by Lina Zarivach

Page 2: 1 Practical Pluggable types for Java Chris Andreae James Noble Victoria University of Wellington Shane Arkus Todd Millstein University of California Presented

2

Existing type systems are not sufficient

Non-null types Declaring and Checking Non-null Types by M.

Fahndrich, OOPSLA’03 Non-Null Safety in Eiffel by B. Meyer,

ECOOP’05 Readonly types

Javari by M. Tschantz, OOPSLA’05 Other type systems

Confined Types by J. Vitek, OOPSLA’99 …

Page 3: 1 Practical Pluggable types for Java Chris Andreae James Noble Victoria University of Wellington Shane Arkus Todd Millstein University of California Presented

3

Implementation

Ad-hoc: New keywords and compiler reimplementation.

Pluggable type systems: Idea by Gilad Bracha, ’04. Implementation by Andreae, Nobel et.al. ’06:

JavaCOP Define new types with Java Annotations Express new type requirements via JavaCOP

Rule Language

Page 4: 1 Practical Pluggable types for Java Chris Andreae James Noble Victoria University of Wellington Shane Arkus Todd Millstein University of California Presented

4

NonNull types example –Pseudo-Declarative syntax & semanticsclass Person {

@NonNull String firstName = "Chris";

void setFirstName(String newName)

{ firstName = newName; }

}

A JavaCOP rule to discover this case:

rule checkNonNull(Assign a) {

where(nonnull(a.lhs)) {

require(defNonNull(a.rhs)):

error(a,“Assigning possible null to @NonNull variable”);

}

}

newName may be NULL!!!

Page 5: 1 Practical Pluggable types for Java Chris Andreae James Noble Victoria University of Wellington Shane Arkus Todd Millstein University of California Presented

5

javac compiler

JavaCOP Architecture

Java program with

new types

ASTofthe

program

JavaCOPrules

Page 6: 1 Practical Pluggable types for Java Chris Andreae James Noble Victoria University of Wellington Shane Arkus Todd Millstein University of California Presented

6

JavaCOP Rule Language Types

A subset of data types generated in the javac compiler. In particular: AST nodes types Type type Symbol type String and generic List types

Env Globals

Page 7: 1 Practical Pluggable types for Java Chris Andreae James Noble Victoria University of Wellington Shane Arkus Todd Millstein University of California Presented

7

AST Node types

+type : Type+pos : int

Tree

+lhs : Tree+rhs : Tree

AssignClassDef

MethodDef

+selected : Tree+name

Select

+meth : Tree+args

Apply

NewClass

Method call, like meth(args);

Instance creation, like new World(“Hello”);

Field or method selection, i.e., o.field or

o.method;()

Page 8: 1 Practical Pluggable types for Java Chris Andreae James Noble Victoria University of Wellington Shane Arkus Todd Millstein University of California Presented

8

Symbols and Types

+isPrimitive() : Boolean+restype() : Type+outer() : Type

Type

ClassType MethodType

-name-type : Type

Symbol

ClassSymbol VarSymbol MethodSymbol

Symbol Table

Page 9: 1 Practical Pluggable types for Java Chris Andreae James Noble Victoria University of Wellington Shane Arkus Todd Millstein University of California Presented

9

Rules for AST nodes

rule aTreeRule(Tree arg) {<sequence of constraints>

}

rule finalClass(ClassDef c){

require(!c.supertype().getSym().hasAnnotation("Final"));

}

Only one argument of type Tree or subclasses of Tree. The rule will be applied to each node of the specified

type.

Huge API

Page 10: 1 Practical Pluggable types for Java Chris Andreae James Noble Victoria University of Wellington Shane Arkus Todd Millstein University of California Presented

10

Primitive Constraints

require(<condition>);

rule UnconditionalIf (If i){

require(i.cond.getSymbol != globals.trueConst ):

warning(i.cond ,"The body of this if will unconditionally be

executed");

require(i.cond.getSymbol != globals.falseConst ):

warning(i.cond ,"The body of this if will never be executed");

}

Instance of Globals

Page 11: 1 Practical Pluggable types for Java Chris Andreae James Noble Victoria University of Wellington Shane Arkus Todd Millstein University of California Presented

11

Conditional Constraints

where(<condition>) {<sequence of constraints>}

rule MicroPatternsExample (ClassDef c){

where(c.isInterface &&

c.getSym.members.length == 0){

require(c.interfaces.length != 1):

warning(globals.NOPOS , "Taxonomy:"+c.flatName );

}

}

Primitive constraint

Page 12: 1 Practical Pluggable types for Java Chris Andreae James Noble Victoria University of Wellington Shane Arkus Todd Millstein University of California Presented

12

Pattern matching

where(<vardefs>; tree => [match using vars]) {<body>}

rule checkNonNullFieldAccess(Assign a){

where(nonnull(a.lhs)) {

where(String n; a.rhs => [%.n]){

require(n.equals("class")):

error(a, "Assigning possibly null field access " +

" to @NonNull variable");

}}}

% is a wildcard forTree.

Page 13: 1 Practical Pluggable types for Java Chris Andreae James Noble Victoria University of Wellington Shane Arkus Todd Millstein University of California Presented

13

Universal quantifier

Similar to the “enhanced for” in Java 1.5.

rule finalMethod(MethodDef m){

forall(Type st: m.enclClass.transitiveSupertypes){

forall(Symbol other:

st.getSymbol.memberLookup(m.name)){

where(other.isFinal){

require(!m.overrides(other, st.getSymbol))

:error(m, "You may not override final method "+other );

}

} } }

Page 14: 1 Practical Pluggable types for Java Chris Andreae James Noble Victoria University of Wellington Shane Arkus Todd Millstein University of California Presented

14

Existential quantifier

Implicit depth-first traversal from a given AST node.

Only nodes that match the declared type of the quantifier variable are considered.

rule allLocalVarsMustBeAssigned (MethodDef m){

forall(VarDef v : m.varDefs()){

where(v.init == null){

exists(Assign a : m){

require(a.lhs.getSymbol == v.getSymbol );

}: error(v,"The variable " + v + "is never assigned");

}}}

Page 15: 1 Practical Pluggable types for Java Chris Andreae James Noble Victoria University of Wellington Shane Arkus Todd Millstein University of California Presented

15

Predicates (package several conditions into boolean function)declare <predicate name>(<vardef> [, <vardef>]) {

<list of constraints> } Invoked by the bodies of rules and other

predicates.

declare nonnull(Tree t){

require(t.holdsSymbol

&& t.getSymbol.hasAnnotation("NonNull"));

}

Page 16: 1 Practical Pluggable types for Java Chris Andreae James Noble Victoria University of Wellington Shane Arkus Todd Millstein University of California Presented

16

Predicates - achieving disjunctive constraints Predicate can have multiple definitions. An invocation of the predicate succeeds if at least

one of the definitions’ bodies is satisfied.

declare defNotNull(Tree t){

require(nonnull(t));

}

declare defNotNull(Tree t){

require(t.type.isPrimitive());

}

declare defNotNull(NewClass t){

require(true);

}

t is non-null if it has @NonNull annotation.

Primitives can’t be null.

New instance can’t be null.

Page 17: 1 Practical Pluggable types for Java Chris Andreae James Noble Victoria University of Wellington Shane Arkus Todd Millstein University of California Presented

17

Error reporting

:<errortype>(<position>,<message>) <errortype> is either error or warning. When a constraint fails to be satisfied, 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")

Page 18: 1 Practical Pluggable types for Java Chris Andreae James Noble Victoria University of Wellington Shane Arkus Todd Millstein University of California Presented

18

Rules for custs – syntactic sugar

rule aCustRule(origType <: custedType @ Tree) {<sequence of constraints>}

Applied to every Tree node that performs explicit or implicit cust

rule checkNonNullCust (a <: b @ e){

where(!nonnull(a)){

require(!nonnull(b)):

error(e, “A possibly null type "+a +" may not be cast to Non-Null type "+b);

}

}

Page 19: 1 Practical Pluggable types for Java Chris Andreae James Noble Victoria University of Wellington Shane Arkus Todd Millstein University of California Presented

19

Applications

A checker for non-null types. A checker for Confined Types. Rules supplied by PMD Java Checker. Rules to identify some micro-patterns. Rules that gather information for software

metrics. An EJB3.0 verifier.

Page 20: 1 Practical Pluggable types for Java Chris Andreae James Noble Victoria University of Wellington Shane Arkus Todd Millstein University of California Presented

20

NonNull assignment

rule checkNonNullAssignment (Assign a){where(nonnull(a.lhs )){

require(defNotNull(a.rhs)):error(a,"Assigning possibly null value to

@NonNull” "+"variable.");}

}

if(x != null){@NonNull Object nonnull_x = x;...}

The above rule will issue an error for this case!!!

Page 21: 1 Practical Pluggable types for Java Chris Andreae James Noble Victoria University of Wellington Shane Arkus Todd Millstein University of California Presented

21

NonNull assignment – flow-sensitive check

rule checkNonNull (Assign a){ where(nonnull(a.lhs )){

require(defNotNull(a.rhs) || safeNullableAssign (a)):error(a,"Assigning possibly null value to @NonNull

"+"variable."); }}declare safeNullableAssign (Assign a){

require(localVariable (a.rhs ));require(safeNullableAssign (env.tree , env.next , a));

}declare safeNullableAssign (Block b, Env e, Assign a){

require(safeNullableAssign (e.tree , e.next , a));}declare safeNullableAssign (If i, Env e, Assign a){

require(nonNullTest(i.cond , a.rhs)&& firstExpression (i.thenpart , a)); }

Env represents traversal information

Page 22: 1 Practical Pluggable types for Java Chris Andreae James Noble Victoria University of Wellington Shane Arkus Todd Millstein University of California Presented

22

Confined types

Confined type is a type whose instances may not be referenced or accessed from outside a certain protection domain.

Confined types protect objects from use by untrusted code.

confunconf

outside

X

Page 23: 1 Practical Pluggable types for Java Chris Andreae James Noble Victoria University of Wellington Shane Arkus Todd Millstein University of California Presented

23

Confined types – example 1

A confined type must not be declared public and must not belong to the unnamed global package.

rule ConfinedExample1 (ClassDef c){

where(confined(c)){ require(!c.isPublic ()): error(c, "Confined class may not be public"); require(c.packge() != globals.emptyPackage): error(c, "Confined class may not be in the default

package");}

}

Page 24: 1 Practical Pluggable types for Java Chris Andreae James Noble Victoria University of Wellington Shane Arkus Todd Millstein University of California Presented

24

Confined Types – example 2 Subtypes of a confined type must be confined and

belong to the same package as their supertype.

rule ConfinedExample2 (ClassDef c){where(confined(c.supertype)){

require(confined(c)):error(c, "An unconfined class may not extend "

+ "a confined superclass");require(c.packge == c.supertype.packge):error(c, “A confined subclass must belong to the

same package as its superclass”);}

}}

Page 25: 1 Practical Pluggable types for Java Chris Andreae James Noble Victoria University of Wellington Shane Arkus Todd Millstein University of California Presented

25

JavaCOP Architecture - details

Compiled rules into Java

Compiled JavaProgram

(bytecode)

Java Program(source)

JavaCOP rules and predicates

Calls methods which

EmitErrors andWarnings

Javac compiler withJavaCOP Framework

JavaCOP FrameworkConstraint Engine

Parsing and

Attribution

BytecodeGeneration Produces

Augmented AST

JavaCOP Compiler

Parse syntax tree

Generate Java source

Performance:~0.02 sec/class

Page 26: 1 Practical Pluggable types for Java Chris Andreae James Noble Victoria University of Wellington Shane Arkus Todd Millstein University of California Presented

26

Conclusions

The first practical framework for pluggable types. Contributions:

Design of JavaCOP Rule Language Implementation of JavaCOP Validation on various kinds of application

Future extensions: More support for flow sensitivity Error clause, that count the number of times a

constraint failed. Increasing the efficiency of checking the constraints.