220 likes | 242 Views
JTL is a logic query language for Java programs that offers a readable syntax and powerful querying capabilities to find code elements with precision. It simplifies code lookup, pattern detection, and static pointcuts, embedded within Java.
E N D
JTL – The Java Tools Language An intuitive query language for Java programs By Tal Cohen ,Yossi Gil and Itay Maman Presented at OOPSLA 2006 Presented by Eyal Dror
Why a Query Language Over Code? • The idea is not new; Existing solutions: • CodeQuest, BDDBDDB, XIRC, JQuery, … • A software engineering tool • Code lookup, Pattern detection (code smells), … • Embedded in programming languages • Static pointcuts in aspect-oriented programming • Type requirements in Concepts and Mixins • And more …
Queries Embedded in the Program • Java 5 already provides code queries • Syntax close to Java • Limited expressive power • A hypothetical alternative (SQL) • Syntax significantly diverts from Java • Difficult to write/read public<T extends Cloneable & Serializable> void f(T ts) { ... } public<SELECT * FROM extends WHERE (super = 'Cloneable' or super = 'Serializeable') and subclass='T' ...> void f(T ts) { … }
More Embedded Queries • Find classes that define a static method that returns int • The regular expression approach: • Very inaccurate • The XQuery approach • Too complicated to be used interactively • And then there’s JTL… static.*int.*\(.*\) • /class/method • [./return/@type=“int" and @modifiers="static"]
So, What IS JTL? • A logic query language over Java programs • As strong as Datalog (implemented over it) • Has an intuitive and readable syntax • Has a simple data model (Three types) • The other solutions fall short
JTL: Unary Predicates • A simple predicate: • Three sub-queries • Space (and comma) denotes conjunction • The subject variable • The hash symbol, #, or “This” denotes the subject variable • A variable in prefix position becomes the subject of the callee • If not specified, defaults to # (the subject) • static, final, etc. are library predicates, not keywords const := static final field; const := # static # final # field;
JTL: Binary Predicates • Binary predicates • Accepts a subject and an additional parameter (in a postfix position) • (Names of Variables/Parameters must begin with a capital letter) • Subject chaining: Repeatedly using a variable as a subject • Can be rewritten using the ampersand operator: has_static_member[X] := class declares X, X static; extends+ Y := extends Y | extends Y', Y' extends+ Y; my_generic_method T := method(T), T extends Serializable, T extends Cloneable; my_generic_method T := method(T), T extends Serializable & Cloneable;
JTL: Quantification { } my_class := class { static int field; field => private; many method; } • Quantifying the members of a class • Subject variable iterates over a set • Each condition must hold • Quantifiers: • Unary: exists, all, no, one, many • Binary: => (implies) • Quantifying with a generator • Default generator for classes: members: • Default quantifier: exists no_abstract_super := class extends+: { no abstract; }
JTL: Matching Java Elements Type literal • Type literals • Passes an exact value to a predicate • Name matching • The subject must match the regular expression • Method signature • The subject must match both expression and argument list sortable_list := class extends /java.util.ArrayList { static final long field 'SerialVersionUID; public void sort(boolean); } Name matching (Regular expression) Method signature pattern
JTL: The Type System • Only three types: • MEMBER • Constructors, methods, fields • TYPE • Interfaces, classes, primitive types, enum types, annotation types • SCRATCH • Used in querying the code dataflow • More about it later …
JTL: Querying Imperative Code • Query access to fields • Field reads and writes • Query method invocation • From interfaces, the declaring type, … unused_private_member := private field, This is F, declared_in C, C inners*: { all !access[F]; } access F := read F | write F;
JTL: Dataflow Analysis (1) • The SCRATCH type • Symbolic names for intermediate computation results • Holds values of temporary variables: • Constants • Method parameters • Results of expression calculation • Values pushed onto the stack by JVM instructions • Library predicates for checking whether a scratch is: • Copied from another scratch • A result of a calculation • Written to/Read from a field • Stored to/loaded from the local variable array • A game of code locations, not of actual values
JTL: Dataflow Analysis (2) • A “chain” method – always returns “this” • Not only by “return this;” • Also captures “ret = this; return ret;” • “scratches:” – The default generator of a method. copy* S := is S | copy S | copy S', S' copy* S; chain_method := !void method { returned => copy* S, S this; }; !void method scratches: { … };
Sample applications of JTL (1) • Pointcut specifications in AOP • Required: primitive fields read/write access • AspectJ: • JTL: get(public boolean *) || set(public boolean *) || get(public byte *) || set(public byte *) || get(public char *) || set(public char *) || get(public double *) || set(public double *) || get(public float *) || set(public float *) || get(public int *) || set(public int *) || get(public long *) || set(public long *) || get(public short *) || set(public short *); primitive := boolean | byte | char | double | float | int | long | short; ppf := public primitive field; pointcut prim_acc() : get(ppf) || set(ppf);
Sample applications of JTL (2) • Generics requirements • C++’s implicit requirements – problematic • Java’s interface requirement – too restrictive • JTL: template<typename T> class ElementPrinter { public: void print(T element) { element.print(); }} interface Printable { void print(); }; (class | interface) { print(); };
Sample applications of JTL (3) • Micro-patterns • Design patterns for classes/interfaces • Taylor the type’s structure according to its use • The “Trait” micro-pattern: • “an abstract class with no instance fields, at least one abstract method, and at least one public concrete instance method which was not inherited from Object.” • JTL’s definition of “Trait”: trait := abstract { no instance field; abstract method; public concrete instance method !declared_in[Object]; }
Sample applications of JTL (4) • Lint-like tests • Detecting undesired coding habits • Loose coupling: Field declarations of concrete Collection types instead of the corresponding interfaces • PMD implements this test as a 45-lines Java class • JTL’s test: loose_coupling := (class | interface) { T method | T field | method(*, T, *); }, T implements /java.util.Collection;
JTL’s Evaluation Scheme • JTL is translated into Datalog • The Datalog program is evaluated top-down • “need to know basis” • The JTL evaluation algorithm does not see more information than it needs • Only necessary facts are extracted from the native predicates • No database setup is needed • The database is built lazily (starts empty!) • A bottleneck in similar applications
Why Relational Model? (vs. AST) • Support for unsorted set metaphor • Sets of packages, classes, members, etc. • Ease of search • Relational model supported by many searching theories • AST search done by cumbersome Visitor design-pattern • Model complexity reflected in the syntax • “avoid hiding inherited instance fields” – more then 30 lines of Java code vs. “class{ field overrides[_] }” • Caching and query optimization • Database query optimization is well established • And more …
A Subtle Issue: Fragility (1) • Q: What’s special about p2? • A: The result of p2 is infinite • The result of p3 MAY be infinite, depending on p4 • Consequences: • Exhaustive Iteration over a closed world, usually the classpath – Performance penalty • Results are fragile! • Dependent on the definition of the world p1 := # extends A, A abstract; p2 := A extends #, A abstract; p3 := A extends #, A abstract, # p4 A; p4 := ...
A Subtle Issue: Fragility (2) • Can we determine whether a query is fragile? • In the general case: No • In JTL’s case: Yes • Requires the native predicates to maintain a simple property • Recently proven by Gil and Zarivach • JTL’s current implementation is more conservative • Subject is not known a runtime error • Works well in most practical situations
Special Thanks To Itay Maman – My presentation is largely based on his JTL presentation