practical pluggable types for java
DESCRIPTION
Chris Andreae James Noble Victoria University of Wellington. Shane Arkus Todd Millstein University of California. Practical Pluggable types for Java. Presented by Lina Zarivach. Existing type systems are not sufficient. Non-null types - PowerPoint PPT PresentationTRANSCRIPT
![Page 1: Practical Pluggable types for Java](https://reader036.vdocuments.mx/reader036/viewer/2022062422/56813dda550346895da7a499/html5/thumbnails/1.jpg)
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: Practical Pluggable types for Java](https://reader036.vdocuments.mx/reader036/viewer/2022062422/56813dda550346895da7a499/html5/thumbnails/2.jpg)
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: Practical Pluggable types for Java](https://reader036.vdocuments.mx/reader036/viewer/2022062422/56813dda550346895da7a499/html5/thumbnails/3.jpg)
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: Practical Pluggable types for Java](https://reader036.vdocuments.mx/reader036/viewer/2022062422/56813dda550346895da7a499/html5/thumbnails/4.jpg)
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: Practical Pluggable types for Java](https://reader036.vdocuments.mx/reader036/viewer/2022062422/56813dda550346895da7a499/html5/thumbnails/5.jpg)
5
javac compiler
JavaCOP Architecture
Java program with
new types
ASTofthe
program
JavaCOPrules
![Page 6: Practical Pluggable types for Java](https://reader036.vdocuments.mx/reader036/viewer/2022062422/56813dda550346895da7a499/html5/thumbnails/6.jpg)
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: Practical Pluggable types for Java](https://reader036.vdocuments.mx/reader036/viewer/2022062422/56813dda550346895da7a499/html5/thumbnails/7.jpg)
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: Practical Pluggable types for Java](https://reader036.vdocuments.mx/reader036/viewer/2022062422/56813dda550346895da7a499/html5/thumbnails/8.jpg)
8
Symbols and Types
+isPrimitive() : Boolean+restype() : Type+outer() : Type
Type
ClassType MethodType
-name-type : Type
Symbol
ClassSymbol VarSymbol MethodSymbol
Symbol Table
…
…
![Page 9: Practical Pluggable types for Java](https://reader036.vdocuments.mx/reader036/viewer/2022062422/56813dda550346895da7a499/html5/thumbnails/9.jpg)
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: Practical Pluggable types for Java](https://reader036.vdocuments.mx/reader036/viewer/2022062422/56813dda550346895da7a499/html5/thumbnails/10.jpg)
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: Practical Pluggable types for Java](https://reader036.vdocuments.mx/reader036/viewer/2022062422/56813dda550346895da7a499/html5/thumbnails/11.jpg)
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: Practical Pluggable types for Java](https://reader036.vdocuments.mx/reader036/viewer/2022062422/56813dda550346895da7a499/html5/thumbnails/12.jpg)
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: Practical Pluggable types for Java](https://reader036.vdocuments.mx/reader036/viewer/2022062422/56813dda550346895da7a499/html5/thumbnails/13.jpg)
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: Practical Pluggable types for Java](https://reader036.vdocuments.mx/reader036/viewer/2022062422/56813dda550346895da7a499/html5/thumbnails/14.jpg)
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: Practical Pluggable types for Java](https://reader036.vdocuments.mx/reader036/viewer/2022062422/56813dda550346895da7a499/html5/thumbnails/15.jpg)
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: Practical Pluggable types for Java](https://reader036.vdocuments.mx/reader036/viewer/2022062422/56813dda550346895da7a499/html5/thumbnails/16.jpg)
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: Practical Pluggable types for Java](https://reader036.vdocuments.mx/reader036/viewer/2022062422/56813dda550346895da7a499/html5/thumbnails/17.jpg)
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: Practical Pluggable types for Java](https://reader036.vdocuments.mx/reader036/viewer/2022062422/56813dda550346895da7a499/html5/thumbnails/18.jpg)
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: Practical Pluggable types for Java](https://reader036.vdocuments.mx/reader036/viewer/2022062422/56813dda550346895da7a499/html5/thumbnails/19.jpg)
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: Practical Pluggable types for Java](https://reader036.vdocuments.mx/reader036/viewer/2022062422/56813dda550346895da7a499/html5/thumbnails/20.jpg)
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: Practical Pluggable types for Java](https://reader036.vdocuments.mx/reader036/viewer/2022062422/56813dda550346895da7a499/html5/thumbnails/21.jpg)
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: Practical Pluggable types for Java](https://reader036.vdocuments.mx/reader036/viewer/2022062422/56813dda550346895da7a499/html5/thumbnails/22.jpg)
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: Practical Pluggable types for Java](https://reader036.vdocuments.mx/reader036/viewer/2022062422/56813dda550346895da7a499/html5/thumbnails/23.jpg)
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: Practical Pluggable types for Java](https://reader036.vdocuments.mx/reader036/viewer/2022062422/56813dda550346895da7a499/html5/thumbnails/24.jpg)
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: Practical Pluggable types for Java](https://reader036.vdocuments.mx/reader036/viewer/2022062422/56813dda550346895da7a499/html5/thumbnails/25.jpg)
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: Practical Pluggable types for Java](https://reader036.vdocuments.mx/reader036/viewer/2022062422/56813dda550346895da7a499/html5/thumbnails/26.jpg)
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.