AUTHOR(S):
John Rose
OVERVIEW
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.
BACKGROUND:
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.
FEATURE SUMMARY:
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 example:
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 = ...;
mh.invoke();
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 = x.foo("ABC").bar(42).baz();
MAJOR ADVANTAGE:
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.
MAJOR BENEFIT:
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.)
MAJOR DISADVANTAGE:
The JLS gets more complicated.
ALTERNATIVES:
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.
EXAMPLES:
See above and below (in the specification) for one-line examples demonstrating each aspect of the syntax and type rules.
void test(MethodHandle mh)
BEFORE/AFTER
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
private static Object method1(Object x)
// function pointer, old style:
public static Method1 method1Ref() {
return new Method1() {
// there is a new classfile per expression reference
public Object apply(Object arg)
}
}
// function pointer, new style:
public static MethodHandle method1Ref()
}
class Bar {
// compiled method for lambda
// call-site cache, old style:
private static Method1 csc42 = null;
private static Object method2(Object x)
// call-site cache, new style:
private static Dynamic method2(Dynamic x)
static
private static Object bootstrapDynamic(java.dyn.CallSite site, Object... args)
}
class MOP {
// shared logic for resolving call sites
public static executeCallSite(java.dyn.CallSite site, Object... args) {
MethodHandle target = site.target();
if (target == null)
return MethodHandles.invoke(target, args);
}
}
SIMPLE EXAMPLE:
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[]
;
greeter(av[0] + " (from a statically linked call site)");
for (String whom : av)
}
static void greeter(String 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
private static Object bootstrapDynamic(CallSite site, Object... args)
}
ADVANCED EXAMPLE:
(See before-and-after MOP example above.)
DETAILS
SPECIFICATION:
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/
(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; // type (Dynamic) -> void
int y = Dynamic.<int>myHashCode((Object)x); // type (Object) -> int
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) -> void
1.5 No checked exceptions are produced by any call to Dynamic.
try
catch (IOError 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; // identical meaning with previous line
x.foo().bar().baz(); // 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
((Dynamic)null).looksBad(42); // identical meaning with previous line
1.8 No other member selection expressions involving Dynamic are allowed, including selection of fields, or of methods of java.lang.Object.
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 javadocs
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; // type (Dynamic) -> void
int y = mh3.<int>invoke((Object)x); // type (Object) -> int
boolean z = mh4.<boolean>invoke(x, y); // type (Dynamic, int) -> boolean
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) -> void
2.5 No checked exceptions are produced by the call expression.
try
catch (IOError ee) { } // a compile-time error
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 292.)
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
// 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 token.
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")
static #"int" valueOf(int #"int")
public int intValue()
public long longValue()
public float floatValue()
public double doubleValue()
public String toString()
}
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 rejected
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()
// must be rejected
void f()
// 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 http://blogs.sun.com/jrose/entry/symbolic_freedom_in_the_vm 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
ExoticIdentifier: # " ExoticIdentifierCharacters "
ExoticIdentifierCharacters:
ExoticIdentifierCharacter ExoticIdentifierCharacters
ExoticIdentifierCharacter:
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
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; // prints "foo"
System.out.println; // 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.)
COMPILATION:
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:
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.
LIBRARY SUPPORT:
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 expertise.
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 environment.
REFLECTIVE APIS:
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.
OTHER CHANGES:
Javap needs to disassemble invokedynamic instructions.
Javap needs to be robust about unusual identifier spellings. (It already is, mostly.)
MIGRATION:
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.
COMPATIBILITY
BREAKING CHANGES:
None. All changes are associated with previously unused types and/or syntaxes.
EXISTING PROGRAMS:
No special interaction. In earlier class files invokedynamic is an illegal opcode, and java.dyn.Dynamic is a previously unused type name.
REFERENCES
EXISTING BUGS:
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
URL FOR PROTOTYPE:
General:
http://hg.openjdk.java.net/mlvm/mlvm/langtools
http://hg.openjdk.java.net/mlvm/mlvm/langtools/file/tip/nb-javac/
Invokedynamic and method handles:
http://hg.openjdk.java.net/mlvm/mlvm/langtools/file/tip/meth.txt
http://hg.openjdk.java.net/mlvm/mlvm/langtools/file/tip/meth.patch
Exotic identifiers:
http://hg.openjdk.java.net/mlvm/mlvm/langtools/file/tip/quid.txt
http://hg.openjdk.java.net/mlvm/mlvm/langtools/file/tip/quid.patch
Casting rules for Dynamic:
http://hg.openjdk.java.net/mlvm/mlvm/langtools/file/tip/dyncast.txt
http://hg.openjdk.java.net/mlvm/mlvm/langtools/file/tip/dyncast.patch