PROPOSAL: language support for JSR 292

John Rose John.Rose at Sun.COM
Mon Mar 30 01:41:36 PDT 2009

Here is a text form of the proposal, for the archives.  The wiki form  
should be equivalent at the moment, but as edits are made the wiki  
form will be normative.

Best wishes,
-- John


John Rose


Create source-code syntaxes for using new JVM features from JSR 292.   
These are invokedynamic instructions, method handle invocation,  
certain relaxed conversions, and exotic identifiers.


At the JVM level, an invokedynamic instruction is used to call methods  
which have linkage and dispatch semantics defined by non-Java  
languages.  Again, a JVM-level invokevirtual instruction has slightly  
altered linkage rules when the target class method is  
java.dyn.MethodHandle.invoke: The change is that any type signature is  
acceptable, and the JVM will make a type-safe method call, regardless  
of the signature.  In addition, the JVM already accepts (since Java 5)  
any of a large set of strings as field, method, and class identifiers,  
and many languages will use such identifiers beyond the limits of the  
Java identifier syntax.  Finally, the JVM verifier already accepts  
(since the beginning) arbitrary reference values for any interface  
type, and it is useful to allow at least one interface type to serve  
as a wild-card type.


We will make small, localized modifications the Java language to make  
it easy to with with these JVM features (old and new).  This will  
allow Java code to interoperate with and/or implement libraries in non- 
Java languages.  The changes are as follows:

1. dynamic invocation, general case

The interface java.dyn.Dynamic may be used with the static call syntax  
to form an invokedynamic call site.  The method name may be any Java  
identifier (including an exotic one; see point 3).  The arguments may  
be of any number and type.  A type argument can optionally supply the  
return type, in the existing <T> syntax.  In effect, java.dyn.Dynamic  
appears to have an infinite number of methods, of every possible name  
and signature.  More details are given below, but here is a first  

     Object x = Dynamic.getMeSomething();

(As defined by JSR 292, an invokedynamic call site is linked to a  
target method under the control of an application-defined bootstrap  
method.  The linkage state is determined by a method handle with the  
same type descriptor as the call site itself.)

2. method handle invocation

Method handles (class java.dyn.MethodHandle) provide the "plumbing"  
behind any invokedynamic instruction.  There are library routines for  
creating and adapting them, as specified by JSR 292.  In addition, it  
is necessary to provide a way of invoking a method handle as an  
explicit target, rather than implicitly as the linked target of an  
invokedynamic instruction.  Since a method handle invocation (like  
invokedynamic itself) can have any argument types and return value,  
method handles also need a special extension for invocation.  As for  
type Dynamic, the type MethodHandle accepts an infinite variety of non- 
static calls to the method named "invoke".  The argument and return  
types for the descriptor presented to the JVM are determined as for  
invokedynamic calls.  Here is a first example:

     MethodHandle mh = ...;

3. exotic identifiers

The grammar for Java identifiers is extended to include "exotic  
identifiers", whose spellings can be any sequence of characters, as  
long as they avoid certain minor restrictions imposed by the JVM.  An  
exotic identifier is introduced by a hash mark, which is immediately  
followed by a string literal.  No special treatment is given to the  
identifier, other than ensuring that its spelling contains exactly the  
character sequence denoted by the string literal.  Details are given  
below; here is an example:

     int #"strange variable name" = 42;
     System.out.println(#"strange variable name");  // prints 42

4. conversion rules for interface Dynamic

The type Dynamic has another use which is synergistically related to  
its role in encoding invokedynamic calls.  It also serves as a dynamic  
version of a wildcard type.  It is a bare reference with no regular  
methods, not even those of java.lang.Object.  As a bare reference, it  
can be freely converted from any other type and to Object.  With a  
cast, it can be converted to any other type.  This works together with  
the invokedynamic syntax to allow dynamic method calls to be chained.   
(As a point of comparison, C# 4.0 has a similar integration between a  
new type "dynamic" and DLR call sites.)  More details are below; here  
is an example:

    Dynamic x = (any type of expression can go here);
    Object  y ="ABC").bar(42).baz();


These changes allow full access to invokedynamic and related new JVM  
features from JSR 292.  This allows Java to interoperate with new JVM  
languages.  It also enables Java to serve well as an language  
implementation or systems programming language.


Much greater ease of creating, for the JVM, with javac, new  
programming languages and language runtimes.

(The potential opportunity cost is that language implementors who  
presently use Java as a systems programming language will be forced to  
stay down at the bytecode assembly level, making them slower to adopt  
the JVM for their work.)


The JLS gets more complicated.


The only viable alternative is assembly coding parts of the system  
which must interoperate with new languages.  This will discourage the  
creation of common runtimes and libraries, and greatly reduce the  
synergy between languages.


See above and below (in the specification) for one-line examples  
demonstrating each aspect of the syntax and type rules.

     void test(MethodHandle mh) {
         mh.invoke("world", 123);
         // previous line generates invokevirtual  
         Dynamic.greet("hello", "world", 123);
         // previous line generates invokedynamic  
         // enclosing class must register a bootstrap method (handle)  
to link Dynamic.greet


There are no concise before/after examples for these language features  
per se, because without the new syntax, dynamic language implementors  
must resort to assembly code.

But, here is a mocked up example that shows how call site caches can  
be created before and after JSR 292.  This is for no particular  
language; call it MyScript.  Note the use of the proposed features to  
form and manage dynamic call sites.

     class Foo {
       // compiled method for lambda (x) { print "Hello, "+x }
       private static Object method1(Object x) {
         System.out.println("Hello, "+x);
         return null;
       // function pointer, old style:
       public static Method1 method1Ref() {
         return new Method1() {
           // there is a new classfile per expression reference
           public Object apply(Object arg) { return method1(arg); }
       // function pointer, new style:
       public static MethodHandle method1Ref() {
         // it all happens in one classfile
         return MethodHandles.findStatic(Foo.class, "method1",

     class Bar {
       // compiled method for lambda (x) { x.ready? }
       // call-site cache, old style:
       private static Method1 csc42 = null;
       private static Object method2(Object x) {
         Method1 tem = csc42;
         // complex machinery with little hope of optimization
         if (tem == null)
           csc42 = tem = MOP.resolveCallSite(Foo.class, "ready?", x);
         return tem.apply(x);
       // call-site cache, new style:
       private static Dynamic method2(Dynamic x) {
         // native to the JVM and the JIT
         return x.#"myscript:ready?"();
       static { Linkage.registerBootstrapMethod("bootstrapDynamic"); }
       private static Object bootstrapDynamic(java.dyn.CallSite site,  
Object... args) {
         return MOP.executeCallSite(site, args);

     class MOP {
       // shared logic for resolving call sites
       public static executeCallSite(java.dyn.CallSite site, Object...  
args) {
         MethodHandle target =;
         if (target == null) {
           target = resolveCallSite(site.callerClass(),,  
           site.setTarget(target);  // next time it will be a direct  
         return MethodHandles.invoke(target, args);


This example greets the world using (a) normal static linkage, (b)  
direct method handle invocation, and (c) a lazily linked call site  
(invokedynamic).  The output from the "bootstrap" routine appears only  
once, after which the linked call site runs by directly calling the  
target method, with no reflection.

     import java.dyn.*;

     public class Hello {
	public static void main(String... av) {
	    if (av.length == 0)  av = new String[] { "world" };
	    greeter(av[0] + " (from a statically linked call site)");
	    for (String whom : av) {
		greeter.<void>invoke(whom);  // strongly typed direct call
		// previous line generates invokevirtual  
		Dynamic x = whom;
		x.hail();                    // weakly typed invokedynamic
		// previous line generates invokedynamic  

	static void greeter(String x) { System.out.println("Hello, "+x); }
	// intentionally pun between the method and its reified handle:
	static MethodHandle greeter
	    = MethodHandles.findStatic(Hello.class, "greeter",
				       MethodType.make(void.class, String.class));

	// Set up a class-local bootstrap method.
	static { Linkage.registerBootstrapMethod("bootstrapDynamic"); }
	private static Object bootstrapDynamic(CallSite site, Object... args) {
	    assert(args.length == 1 && == "hail");  // in lieu of  
	    System.out.println("set target to adapt "+greeter);
	    MethodHandle target = MethodHandles.convertArguments(greeter,  
	    System.out.println("calling the slow path; this should be the  
last time!");
	    return MethodHandles.invoke(target, args);


(See before-and-after MOP example above.)



1.1 The type java.dyn.Dynamic shall be defined as an empty interface  
with no supertypes.  It is an error if Dynamic is defined as a class,  
or if it has any supertypes, or if it defines any members.  It does  
not have the usual implicit supertype of Object.

     package java.dyn;
     public interface Dynamic /*must be empty*/ { /*must be empty*/ }

(The complete lack of supertypes makes it an unusual type, on a par  
with Object.  Of course the JVM verifier will allow free  
interconversion between Object and Dynamic.  This unusual "sterility"  
allows Java complete access to all degrees of freedom in the JVM's  
invokedynamic instruction.)

1.2 The type name Dynamic may be qualified with any method name  
whatever, and invoked on any number and type of arguments.   The  
compiler generates an invokedynamic call site with the given name and  
a descriptor (symbolic type signature) derived from the erasure of the  
static types of all the arguments.  In this way, an invokedynamic  
instruction can be written in Java to use any of the full range of  
calling sequences (i.e., descriptors) supported by the JVM.  Neither  
the JVM instruction nor the Java syntax is limited in its use of  
argument types.

     Dynamic.anyNameWhatever();   // no argument types
     Dynamic.anotherName("foo", 42);  // argument types (String, int)

1.3 Any call to a method in Dynamic accepts an optional type parameter  
which specifies the return type of the call site's descriptor.  The  
type parameter may any type whatever, including void or a primitive  
type.  If it is omitted it defaults to the type java.dyn.Dynamic  
itself.  (See part 4 for conversion rules involving Dynamic.)

     Dynamic x = Dynamic.myGetCurrentThing();  // type () -> Dynamic
     Dynamic.<void>myPutCurrentThing(x);  // type (Dynamic) -> void
     int y = Dynamic.<int>myHashCode((Object)x);  // type (Object) ->  
     boolean z = Dynamic.<boolean>myEquals(x, y);  // type (Dynamic,  
int) -> boolean

(Rationale: Although it is strange for non-references to appear in the  
syntactic position of type arguments, this design is far simpler than  
inventing a completely new syntax for specifying the return type of  
the call site, as some early prototypes did.)

1.4 For the purposes of determining the descriptor of the  
invokedynamic instruction, null arguments (unless casted to some other  
type) are deemed to be of reference type java.lang.Void.  This is a  
pragmatic choice, compatible with the verifier and partially coherent  
with the meaning of the type Void, since it happens to allow only null  
reference values.  Conversely, void method return values are reflected  
as null values.  The type Void will appear only to the bootstrap  
method, and will serve notice that the call site contains a null,  
rather than an explicitly typed reference.

     Dynamic.myPrintLine(null);  // type (Void) -> Dynamic
     Dynamic.<void>foo((String)null, null);  // type (String, Void) ->  

1.5 No checked exceptions are produced by any call to Dynamic.

     try {; } catch (Exception ee) { }  // a compile- 
time error

1.6 In order to support chained invokedynamic expressions, any  
reference of type Dynamic may also be qualified with any name and  
invoked on any number and type of arguments.  Since the invokedynamic  
instruction is receiverless (symmetrical in all arguments), the target  
value of the method invocation expression is pushed first on the stack  
before the other arguments, while its static type (which is always  
Dynamic) is prepended to the call descriptor presented to the JVM.

     Dynamic x = ...;
     boolean z = Dynamic.<boolean>myEquals(x, 42);  // type (Dynamic,  
int) -> boolean
     boolean z = x.<boolean>myEquals(y);  // identical meaning with  
previous line;   // 3 invokedynamic calls of type (Dynamic)  
-> Dynamic

1.7 As with any other expression of Dynamic type, qualifying it with a  
method name has precisely the same effect as qualifying the type  
Dynamic itself, and inserting the previously qualified expression as  
the first method argument.  In particular, there is no special check  
for null references.

     Dynamic.looksBad((Dynamic)null, 42);  // type (Dynamic, int) ->  
     ((Dynamic)null).looksBad(42);  // identical meaning with previous  

1.8 No other member selection expressions involving Dynamic are  
allowed, including selection of fields, or of methods of  

1.9 Although it is perhaps not very useful, Dynamic can be used in  
other Java constructs that accept interface types, with unchanged  
meaning.  A class or interface may specify Dynamic as a supertype, and  
the effect is similar to any other empty interface appearing as a  
supertype:  No new methods are defined, and the instanceof and cast  
expressions work as they always have.  (Non-inheritance of  
invokedynamic methods prevents Dynamic from disturbing static scoping  
of any type other than Dynamic itself.)  Java code may declare  
variables, arrays, fields, arguments, and return values of type  
Dynamic or its subtypes.

2.1 The class java.dyn.MethodHandle shall be defined (external to this  
specification) without any method named "invoke".  It is an error if  
it or any of its supertypes define a method named "invoke".  (In any  
case, such supertypes are a fixed part of the Java APIs and/or  
implementations.  JSR 292 happens to define a method named "type" on  
method handles.)

     package java.dyn;
     public class MethodHandle { ... }

2.2 Any reference of type MethodHandle may be qualified with the  
method name "invoke" and invoked on any number and type of arguments.   
Only the method named "invoke" is treated this new way.  All other  
expressions involving MethodHandle are unchanged in meaning, including  
selection of members other than "invoke", casting, and instanceof.

     MethodHandle mh = ...;
     mh.invoke("foo", 42);  // argument types (String, int)
     MethodType mtype = mh.type();  // no new rules here; see JSR 292  
     mh.neverBeforeSeenName();  // no new rules; must raise an error

In effect, java.dyn.MethodHandle appears to have an infinite number of  
non-static methods named "invoke", of every possible signature.

(In fact, JSR 292 specifies that each individual method handle has a  
unique type signature, and may be invoked only under that specific  
type.  This type is checked on every method handle call.  JSR 292  
guarantees runtime type safety by requiring that an exception be  
thrown if a method handle caller and callee do not agree exactly on  
the argument and return types.  The details of this check are not part  
of this specification, but rather of the MethodHandle API.)

2.3 A method handle call on "invoke" accepts an optional type  
parameter to specify the return type.  As with Dynamic, the type  
parameter to MethodHandle.invoke may be any type, including void or a  
primitive type. If it is omitted it defaults to Dynamic.

     MethodHandle mh1, mh2, mh3, mh4; ...
     Dynamic x = mh1.invoke();  // type () -> Dynamic
     mh2.<void>invoke(x);  // type (Dynamic) -> void
     int y = mh3.<int>invoke((Object)x);  // type (Object) -> int
     boolean z = mh4.<boolean>invoke(x, y);  // type (Dynamic, int) ->  

2.4 As with Dynamic, otherwise untyped null argument values are  
treated as if they were of type Void.

     mh1.invoke(null);  // type (Void) -> Dynamic
     mh2.<void>invoke((String)null, null);  // type (String, Void) ->  

2.5 No checked exceptions are produced by the call expression.

     try { mh.invoke(); } catch (Exception ee) { }  // a compile-time  

2.6 As usual, if a null value typed as a method handle is qualified  
with the method name "invoke", the expression must terminate  
abnormally with a NullPointerException.

     MethodHandle nmh = null;
     nmh.invoke();       // must produce a NullPointerException

2.7 If a class extends MethodHandle, it does not inherit any of the  
implicitly defined "invoke" methods.  To invoke a subclass of a method  
handle, it must first be cast to MethodHandle per se.  (Non- 
inheritance of "invoke" methods prevents MethodHandle from disturbing  
static scoping of any type other than MethodHandle itself.  Note that  
public method handle subclasses are not necessarily a feature of JSR  

     class DirectMethodHandle extends MethodHandle { ... }
     DirectMethodHandle dmh = mh;
     mh.invoke<void>();  // must be rejected: special MH.invoke not  
visible here

2.8 The bytecode emitted for any call to MethodHandle.invoke is an  
invokevirtual instruction, exactly as if a public virtual method of  
the desired descriptor were already present in java.dyn.MethodHandle.

     mh.<void>invoke(1);  // produces an invokevirtual instruction
     class MethodHandle { ... public abstract void invoke(int  
x); ... }  // hypothetical overloading of 'invoke'
     mh.invoke(1);        // would produce an identical invokevirtual,  
if that overloading could exist

3.1 The two-character sequence '#' '"' (hash and string-quote, or  
ASCII code points 35 and 24) introduces a new token similar in  
structure to a Java string literal.  The token is in fact an  
identifier (JLS 3.8), which may be used for all the same syntactic  
purposes as ordinary identifiers are used for.

     int #"strange variable name" = 42;
     System.out.println(#"strange variable name");  // prints 42

This is true whether or not the characters are alphanumeric, or  
whether they happen (when unquoted) to spell any  Java Java keyword or  

     int #"+", #"\\", #"42" = 24;
     System.out.println(#"42" * 100);  // prints 2400

     // another take on java.lang.Integer:
     class #"int" extends Number {
       final int #"int";
       #"int"(int #"int") { this.#"int" = #"int"; }
       static #"int" valueOf(int #"int") { return new #"int"(#"int"); }
       public int intValue() { return #"int"; }
       public long longValue() { return #"int"; }
       public float floatValue() { return #"int"; }
       public double doubleValue() { return #"int"; }
       public String toString() { return String.valueOf(#"int"); }

3.2 The spelling of the identifier is obtained by collecting all the  
characters between the string quotes.  Every string escape sequence  
(JLS 3.10.6) is replaced by the characters they refer to.  As with  
other tokens, this character collection occurs after Unicode escape  
replacement is complete (JLS 3.3).

     int #"\'\t" = 5;  // a two-character identifier
     System.out.println(#"'\u0009");  // prints 5

3.3 In particular, if the resulting sequence of characters happens to  
be a previously valid Java identifier, both normal and exotic forms of  
the same identifier token may be freely mixed.

     int #"num" = 42, scale = 100;
     System.out.println(num * #"scale");  // prints 4200

3.4 An exotic identifier may not be empty.  That is, there must be at  
least one character between the opening and closing quotes.

     int #"";  // must be rejected

3.5 Certain characters are treated specially within exotic identifiers  
even though they are not specially treated in string or character  
literals.  The following so-called "dangerous characters" are illegal  
in an exotic identifier unless preceded by a backslash:  / . ; < >  
[ ].  If a dangerous character is preceded by a backslash, the  
backslash is elided and the character is collected anyway.  Depending  
on the ultimate use of the identifier, the program may be eventually  
rejected with an error.  This must happen if and only if the escaped  
character would otherwise participate in a bytecode name forbidden by  
the Java 5 JVM specification.

     class #"foo/Bar" { }  // not a package qualifier, must be rejected
     class #"foo.Bar" { }  // not a package qualifier, must be rejected
     x.#"<init>"();        // not a method call; must be rejected
     x.#"f(Ljava/lang/Long;)"(0);  // not a method descriptor; must be  

3.5.1 Specifically, the compiler must reject a program containing an  
exotic identifier with an escaped dangerous character happen if any of  
these is true: (a) the identifier is used as part or all of the  
bytecode name of a class or interface, and it contains any of / . ; [,  
or (b) the identifier is used as a part or all of the bytecode name of  
a method, and it contains any of / . ; < >, or (c) the identifier is  
used as a part or all of the bytecode name of a field, and it contains  
any of / . ;.  Note that close bracket ] will always pass through; it  
is included in these rules simply for symmetry with open bracket ].

     class #"java/io"  { }  // must be rejected
     class #"java\/io" { }  // must be rejected (perhaps in an  
assembly phase)

     class #"<foo>"    { }  // must be rejected
     class #"\<foo\>"  { }  // legal (but probably a bad idea)

     void f() { int #"&yen;"  = '\u00A5'; }  // must be rejected
     void f() { int #"&yen\;" = '\u00A5'; }  // legal (but probably a  
bad idea)

     class #"]"  { int #"]";  void #"]"()  {} }  // must be rejected
     class #"\]" { int #"\]"; void #"\]"() {} }  // legal (but  
probably a bad idea)

These rules support the need for avoiding dangerous characters as a  
general rule, while permitting occasional expert use of names known to  
be legal to the JVM.  However, there is no provision for uttering the  
method names "<init>" or "<clinit>".  Nor may package prefixes ever be  
encoded within exotic identifiers.

3.6 Any ASCII punctuation character not otherwise affected by these  
rules may serve as a so-called "exotic escape character".  That is, it  
may be preceded by a backslash; in this case both it and the backslash  
is collected (as a pair of characters) into the exotic identifier.   
Specifically, these characters are ! # $ % & ( ) * + , - : = ?  @ ^ _  
` { | } ~ and no others.

     int #"="   = 42;
     int #"\="  = 99;
     System.out.println(#"=");  // must print 42 not 99

These escapes are passed through to the bytecode level for further use  
by reflective applications, such as a bootstrap linker for  
invokedynamic.  Such escapes are necessary at the level of bytecode  
names in order to encode (mangle) the dangerous characters.  By  
sending both the backslash and the exotic escape character through to  
the bytecode level, we avoid the problem of multiple escaping (as is  
seen, for example, with regexp packages).

Although Java has not worked this way in the past, the need for  
multiple phases of escaping motivates it here and now.  Compare this  
quoting behavior with that of the Unix shells, which perform delayed  
escaping for similar reasons:
     $ echo "test: \$NL = '\12'"
     test: $NL = '\12'

(See for a  
proposal that manages bytecode-level mangling of exotic names.  This  
proposal is independent of the present specification.)

3.7 Here is the combined grammar for exotic identifiers, starting with  
a new clause for Identifier (JLS 3.8):

     Identifier: ...
     ExoticIdentifier: # " ExoticIdentifierCharacters "
       ExoticIdentifierCharacter ExoticIdentifierCharacters
       StringCharacter but not DangerousCharacter
       \ DangerousCharacter  /* the backslash is elided and the  
character is collected */
       \ ExoticEscapeChar    /* both the backslash and the character  
are collected */
     DangerousCharacter: one of / . ; < > [ ]
     ExoticEscapeChar: one of ! # $ % & ( ) * + , - : = ? @ ^ _ `  
{ | } ~

3.8 This construct does not conflict with any other existing or  
proposed use of the hash character.  In particular, if the hash  
character were to be defined as a new sort of Java operator, it would  
not conflict with this specification.  Even if it were to be a  
construct which could validly be followed by a normal Java string  
literal, any ambiguity between the constructs could be resolved in  
favor of the operator by inserting whitespace between the hash and the  
opening quote of the string literal.

3.9 Exotic identifiers are occasionally useful for creating  
dynamically linkable classes or methods whose names are determined by  
naming scheme external to Java.  (They may also be used for  
occasionally avoiding Java keywords, although a leading underscore  
will usually do just as well.)  They are most crucially useful for  
forming invokedynamic calls, when the method name must refer to an  
entity in another language, or must contain structured information  
relevant to a metaobject protocol.

     package my.xml.tags;
     class #"\<pre\>" { ... }

     package my.sql.bindings;
     interface Document { String title(); Text #"abstract"(); int  
#"class"(); ... }

     Dynamic mySchemeVector = ...;
     Dynamic x = Dynamic.#"scheme:vector-ref"(mySchemeVector, 42);

4.1 As specified above, the interface java.dyn.Dynamic has no  
supertypes or members.  As such, it is a bare reference type.  (As an  
arbitrary relation, the superclass of Dynamic[] is Object[].)  We  
define a "dynamic expression" as an expression of static type  
Dynamic.  Dynamic expressions can also be readily qualified to form  
invokedynamic calls.  We extend the usefulness of dynamic expressions  
by allowing them to interact with other Java expressions and statements.

    Dynamic x = (any reference expression can go here);

4.2 The types Dynamic and Object may be freely interconverted, even  
though neither is a supertype of the other.  (The JVM verifier already  
allows this, for any interface and Object, or any two interfaces.  We  
expose one specific instance of this general principle by special- 
casing Dynamic.)  No runtime check is emitted when an Object is  
converted to Dynamic.  (That is, the compiler must never emit a  
checkcast to java.dyn.Dynamic.)

    Object  x = (Object) "foo";
    Dynamic y = x;
    Object  z = y;
    System.out.println(x);    // prints "foo"
    System.out.println(y);    // prints "foo"
    System.out.println(z);    // prints "foo"

The middle line shows the limited way in which static overloading  
interacts with dynamic typing.  The dynamic argument selects the  
Object overloading of "println" because Dynamic implicitly converts to  
Object.  It also converts to any of the other types accepted by  
overloading of "println", but those other types would require a cast.   
Specifically, although the reference happens to be of type String, the  
String overloading of "println" will not be selected.  As it happens,  
"println" produces consistent results anyway.

4.3 Any type may be undergo argument, assignment, or casting  
conversion to Dynamic, by first converting to Object.  If the original  
type is a primitive, it undergoes boxing conversion.

     Dynamic x = 42;  // (Dynamic) (Object) Integer.valueOf(42)
     Dynamic x = "foo";  // (Dynamic) (Object) "foo"

(No bytecode need be emitted for such conversions, except for boxing.   
The compiler must not emit a checkcast to Dynamic.)

4.4 Dynamic expressions can be cast to any reference type, by first  
converting to Object, then casting, if that latter cast would be  
legal.  (There is no special support for casting Dynamic to generic  
type instances.)

     Dynamic x = ...;
     String y = (String) x;  // (String) (Object) x

(The compiler must not emit a checkcast to java.dyn.Dynamic.)

4.5 Dynamic expressions can be cast to any primitive type, by first  
casting to the corresponding wrapper type then unboxing.

    Dynamic x = ...;
    int y = (int) x;  // (int) (Integer) (Object) x

4.6 The expression syntaxes with predefined meaning for dynamic sub- 
expressions are those which perform the conversions described above.   
These are assignment "=" and casts.  Dynamic expressions may also be  
tested with instanceof.  Also, Dynamic values may be declared,  
assigned to variables, passed as method or constructor arguments, and  
returned from methods.

But, the Java operators "==" "!=" "+" "+=" on reference types are  
clarified to apply only to reference types which are java.lang.Object  
or one of its subtypes; they do not have a predefined meaning if  
either operand is dynamic.  The "synchronized" and "throw" statements  
cannot be applied to dynamic expressions.

(In general, Java expressions which detects object reference identity  
will not work directly on dynamic expressions.  Such expressions may  
be explicitly cast to Object, however.)


See JSR 292 for the specification of invokedynamic instructions.  In  
brief, they begin with a new opcode, a CONSTANT_NameAndType index, and  
end with two required zero bytes.  Method handle invocation is just an  
ordinary invokevirtual instruction, whose class is  
java.dyn.MethodHandle, whose name is "invoke", and whose descriptor is  
completely arbitrary; this requires no special compilation support  
beyond putting a loophole in the method lookup logic.  Exotic  
identifiers require no compilation support beyond the lexer.  (This  
assumes Unicode-clean symbol tables all the way to the backend.)   
There must be a final validity check in the class file assembler; this  
can (and should) be copied from the JVM specification.


Testing will be done the usual way, via unit tests exercising a broad  
variety of signatures and name spellings, and by early access  
customers experimenting with the new facilities.


The JVM-level behavior of the types java.dyn.Dynamic and  
java.dyn.MethodHandle are defined by JSR 292.  Their language  
integration should be defined by an expert group with language  

JSR 292 per se involves extensive libraries for the functionality it  
defines, but they are not prerequisites to the features specified  
here.  Other than exotic identifiers, the features described here have  
no impact except when the java.dyn types exist in the compilation  


The method java.lang.Class.getDeclaredMethod must be special-cased to  
always succeed for MethodHandle.invoke and for Dynamic (any method  
name), regardless of signature.  The JSR 292 JVM has this logic  
already, but it must be exposed out through the Class API.

Only single-result reflection lookups need to be changed.  Multiple- 
method lookups should *not* produce implicitly defined methods.

The javax.lang.model API (which is used internally by javac) does not  
need specialization, because the implicitly defined methods of  
MethodHandle and Dynamic do not ever need to mix with other more  
normal methods.  The static (compile-time) model of Dynamic may not  
present any enclosed elemeents, while that of MethodHandle must not  
present any methods named "invoke".

Facilities which compute type relations (such as  
javax.lang.model.util.Types) may need to be updated to take Dynamic  
into account.  Generally speaking, the new Dynamic conversions operate  
in parallel to the implicit boxing conversions.  That is, they add no  
new subtype or supertype relations, but they provide a few more ways  
for values to be implicitly converted or casted.


Javap needs to disassemble invokedynamic instructions.

Javap needs to be robust about unusual identifier spellings.  (It  
already is, mostly.)


The feature is for new code only.

These language features, along with the related JVM extensions, will  
make it possible for dynamic language implementations (a) to continue  
to be coded in Java, but (b) to avoid the performance and complexity  
overhead of the Core Reflection API.



None.  All changes are associated with previously unused types and/or  


No special interaction.  In earlier class files invokedynamic is an  
illegal opcode, and java.dyn.Dynamic is a previously unused type name.



6754038: writing libraries in Java for non-Java languages requires  
method handle invocation
6746458: writing libraries in Java for non-Java languages requires  
support for exotic identifiers
00TBD00: writing libraries in Java for non-Java languages requires  
permissive Dynamic type



Invokedynamic and method handles:

Exotic identifiers:

Casting rules for Dynamic:

More information about the coin-dev mailing list