Java as a Metalinguistic Framework Vijay Saraswat vijay@saraswat.org June 2002 Outline (20 min) The Java language, and the JVM (30 min) New language concepts, and their implementation (10 min) Questions Java Class-based Single inheritance Members: Fields, Constructors, Methods public/private/protected/abstract/fin al/native/static Methods may be overloaded Interfaces provide signatures No delegation Java provides “capabilities” Type-security State-encapsulation Final methods Unforgeable references Built-in garbage collection Arrays assignment If…then…else, switch for.., while.., do.., continue,break Typed exceptions try…catch, try…finally throw Method calls, return Type hierarchy Control structures Singly rooted Separate “built-in” types Extensive libraries, with native state No generics Threads, synchronization Dynamic Linking Contexts User-defined class loaders Allows container-based computing “The Java Language Specification, 2d ed” Gosling, Joy, Steele, Bracha 2000 Java compilation – the JVM ClassFile { u4 magic cp_info constant_pool[constant_pool_count-1] u2 access_flags; Stack-oriented machine, with fixed stack-frame size. Typed byte codes Objects are heap-allocated. Classes u2 minor_version; u2 constant_pool_count; u2 this_class; u2 super_class; u2 interfaces_count; u2 interfaces[interfaces_count] u2 fields_count; field_info fields[fields_count]; u2 methods_count; method_info methods[method_count]; u2 attributes_count; attribute_info attributes[attributes_count] Verification Preparation Resolution Ported extensively Windows, Sparc, IBM mainframes, cell phones/PDAs (KVM) } “The Java Virtual Machine Specification, 2d ed”, Lindholm and Yellin, 1999 Java Virtual Machine – Byte codes (enumeration) Load and store instructions Move data between local variables and op stack. Object creation and manipulation Arithmetic instructions Add, subtract, mult, divide, remainder, negate, shift, bitwise ops, local variable inc, comparisons Type conversion instructions Operand stack management (un)conditional branches Method invocation and return Push/pop etc Control transfer Create, access fields of classes and instances, load/store arrays to operand stack, casting Virtual, interface, special, static Synchronization Monitorexit, monitorenter Java compilation Compiler Dynamic profiling, JIT optimization Parses Type checks Code generates Dynamic code rewriting Class libraries Garbage collection, object finalization Java as a metalinguistic framework Basic idea Reuse the language framework Syntax, Compiler, runtime system Advantages JL Tools (Myers) Jikes Pizza/GJ compiler Implement the new features through static reasoning (source code, byte code) source-to-source transformation Modifications to the root object. disallowing use of (certain) features/libraries. Time to market -- keeps the cost of developing a new language low! Incrementally replace components (e.g. compiler, run-time system, virtual machine) Disadvantage Suitable only for “Java-like languages” But see Microsoft C# and the Common Runtime System. Some simple examples – Generic types Generic types Introduce parameters into class and method definitions Better than programming at the “top-level” type Implementation Compiles to unchanged JVM. Uses type-erasures, inserts typecasts (which are guaranteed to succed) class LinkedList<A> implements Collection<A> { protected class Node { A elt; Node next = null; Node (A elt) { this.elt = elt;} public LinkedList() {} public void add(A elt) { if (head == null) { head=new Node(elt); tail = head;} else {tail.next=new Node(elt); tail = tail.next;}} }… } “Making the future safe for the past: Adding Genericity to the Java Programming Language” Bracha, Odersky, Stoutamire, Wadler Some object-oriented techniques Get rid of statics – replace by unit classes: Delegates public class Forwarder <S> { public unit class Table <Session implements Key> { S target; public Forwarder(S target) { Hashtable <Session> table; this.target = target;} public void add(Session s) { public void revoke() { table.put(s.getKey()); this.target = null;} }… delegate target; } } Implement by compiling into a “normal” class with a single static field. Implemented by source-tosource compilation Information Flows – extended typechecking Key idea: Static checking of flow annotations Data values are labeled with security policies. Each policy has an owner (security principal) and a set of readers (other principals). E.g. L={o1:r1,r2;o2:r2,r3} Programmer annotates variables x with labels l(x) statically. Compiler “flows” labels, computing a label l(e) for each RHS e in an assignment x = e An assignment x is labelsafe iff l(x) =< l(e). L1 =< L2 =def= for every policy in L1 there is at least one policy in L2 that is at least as restrictive. Operations cause joins of labels to be taken. Compiler “label-checks” program, and outputs Java (stripped of labels). “JFlow: Practical mostly-static information flow control”, Myers, POPL 99 Integrating Concurrent Constraint Programming Motivation Threads, synchronization, locking are poor programming concepts Witness the complexity of the memory model for Java! Alternative: event-loops “promises” Introduce (logic) variables Computation progresses by imposing and checking constraints Agent combinators (A) c c -> A A, A X^A p(t1, …, tn) Program is a collection of definitions: p(X1,…,Xn)::A Constraint system: Herbrand X = f(t1, …, tn), X=Y “Concurrent Constraint Programming”, Saraswat, 1993 Programming in cc(Herbrand) append(X,Y, Z) :: X=_A._X1 -> Z1^(Z=A.Z1, append(X1, Y, Z1)) X = [] -> Z=Y. nrev(X, Y) :: X = _A._X1 -> Z^(nrev(X1, Z), append(Z, [A], Y)) point(In, X, Y, Color) :: In=move(_dX, _dY).In1 -> point(In’, X+dX, Y+dY), In=get(_X1, _Y1).In1 -> X=X1, Y=Y1, point(In1, X, Y, Color). Jcc – CCP in Java Introduce promises (= typed logic variables): just an instance of the given type. A BasicPromise is in one of 4 states: Interface: Promise; basic implementation: BasicPromise Unrealized and unwatched Unrealized and watched Bound Realized Promises may be equated to each other Objects are created as (toplevel) constants (realized), or as (unrealized and unwatched) promises As a result of equatings, object change state: Unrealized -> Bound Unrealized -> Realized Bound -> Realized Any suspended computations are run when a promise is realized. Method invoked on object o is always delegated to the object obtained by dereferencing o. Append in Java, using promises public List append( final List second ) { List me = (List) this.dereference(); if ( me.isUnrealized()) { final List promise = new List(); me.runWhenRealizedDerefed(new Runnable() { public void run() { promise.equate( List.this.append( second ) ); } }); return promise; } return me.appendRealized( second); } private List appendRealized( List second ) { return this.isNull() ? second : new List( this.head, this.rest.append( second )); } Code in jcc Allow “realized” annotations on methods, parameters. Call suspends until the corresponding object is realized. Add “when … catch” and “when…finally” constructs. Implement by compiling into scheme on previous slide. public realized List reverse( final List remainder) { return this.isNull() ? remainder : this.rest.reverse() .append(new List( this.head)); } public realized List append( List second ) { return this.isNull() ? second : new List( this.head, this.rest.append( second )); } Extends to Hybrid CC Timed CCP obtained from CCP by “extending relations through time” Default CCP obtained by allowing detection of absence of information. Hybrid CCP obtained by moving to continuous time. These languages allow a rich plethora of combinators to be defined within the language do … watching… do … until… Jhcc introduces these control constructs into jcc.. Implementation via compilation to JVMs “Timed Default Concurrent Constraint Programming”, Saraswat et al1996 “Computing with continuous change”, Gupta et al 1998 Programming in jhcc public class Furnace implements Plant { public class Controller { const Real heatR, coolR, initTemp; Plant plant; public readOnly Fluent<Real> temp; public void setPlant(Plant p) { this.plant=p;} public inputOnly Fluent<Bool> switchOn; … public Furnace(Real heatR, Real coolR, Real initT ) { } this.heatR = heatR; this.coolR = coolR; this.initTemp = initT; } public class ControlledFurnace { Controller c; Furnace f; public ControlledFurnace(Furnace f, public void run() { Controller c) { temp = initTemp, time always { dot(temp)=heatR} on switchOn; this.c = c; this.f = f;} public void run() { time always {dot(temp)=-coolR} on ~switchOn; }} c.run(); c.setPlant(f); f.run(); } M – the basis for Matrix E Pure capability-based Distributed language Vats and Event loops “Promise”-based architecture M Jcc + inter-JVM communication (SMI+ crypto) Current approach Interpreter in Java http://www.erights.org (Mark Miller et al) Mass Computing People interacting in virtual worlds Networked Users can connect from anywhere, anytime (wireless, wire-line) using appropriate clients (graphical, voice, webbased). Interactive Persistent World state persists through connections, incarnations. Objects are meta-mutable. Secure Users are credentialed, authenticated. No user can bring down a world. Extensible You can create your own objects Resource-sensitive World is populated with stateful objects with which you interact: room, table, chairs, cabinets, assignments, labyrinths, trolls, games, puzzles, assignments, museums, simulations … Users have quotas, own objs Federated Multiple worlds in a federation Objects may migrate Java as a metalinguistic framework Powerful framework Supports quick experimentation with different language features