Eric Bodden (eric.bodden@ec-spride.de)
January 13th, 2012
JSR292 describes a new bytecode, invokedynamic, and a series of new constant-pool entries that, together, allow the execution of invokedynamic instructions. Unlike all other Java bytecode invoke instructions, the target method of an invokedynamic instruction is not defined by the language semantics, but rather by a user-defined method, called the bootstrap method.
The purpose of a bootstrap method is to associate an invokedynamic statement with a CallSite object. A call to this object's getTarget() method will then return a method handle to the invokedynamic statement's target method. Call sites may be constant or mutable, i.e., may or may not return the same method handle object on each call. Each invokedynamic instruction can be associated with its own bootstrap method, or multiple instructions can share the same method.
In addition to its bootstrap method, an invokedynamic instruction can take a number of static arguments. The arguments are called static because the bootstrap method is executed at load time. For the same reason, static arguments are restricted to the argument types that can be encoded in the constant pool.
Finally, an invokedynamic instruction states a method name and a number of regular invocation arguments. Note that, unlike for normal methods, this method name does not have to follow Java's naming conventions; instead it is an uninterpreted Utf8 String.
To summarize, an invokedynamic instruction includes:
The information is stored in the bytecode's constant pool in a rather complex way, using various constant pool entries and a new attribute, BootstrapMethods. Soot's bytecode parser Coffi now parses these entries to create Jimple expressions from invokedynamic bytecodes. The BootstrapMethods attribute is stripped during this process; it will not occur as a tag on the corresponding SootClass. Instead, the attribute is re-generated when Jimple is converted back to bytecode. (see below)
Further information on the bytecode format can be found in the official package documentation for java.lang.invoke.
In the Jimple IR, a invokedynamic bytecode is represented as a JDynamicInvokeExpr, whose constructor expects four arguments:
dynamicinvoke "+" <java.lang.Object (java.lang.Object)>(r1) <jsr292.cookbook.binop.RT: java.lang.invoke.CallSite bootstrapOpLeft(java.lang.invoke.MethodHandles$Lookup, java.lang.String,java.lang.invoke.MethodType,int)>(1)
Here the string following the keyword dynamicinvoke is the uninterpreted Utf8 string denoting the call site's method name. This string appears as an actual string constant so that it can be parsed again by the Jimple parser. (Again, note that any Utf8 string is allowed!) On the next line, the expression contains an unnamed method signature, stripped of any declaring class name and method name (because these were given before). In the above example, r1 is the dynamic argument to this call; according to the signature, it may hold any kind of Object. The last three lines contain a regular staticinvoke expression, representing the bootstrap method and the static constant arguments to invoke it at load time.
The Jimple parser fully supports this syntax, which means that Soot users may directly write Jimple files in the above syntax to create invokedynamic bytecodes.
load.r r0; dynamicinvoke "+" <java.lang.Object (java.lang.Object)> <jsr292.cookbook.binop.RT: java.lang.invoke.CallSite bootstrapOpLeft(java.lang.invoke.MethodHandles$Lookup, java.lang.String,java.lang.invoke.MethodType,int)>(1);
Note that Baf is currently an output-only IR, i.e., there is no parser that could parse Baf instructions back into Soot.
invokedynamic "+" (Ljava/lang/Object;)Ljava/lang/Object; jsr292/cookbook/binop/RT/bootstrapOpLeft(Ljava/lang/invoke/MethodHandles$Lookup; Ljava/lang/String;Ljava/lang/invoke/MethodType;I) Ljava/lang/invoke/CallSite; ((I)1)
This is quite similar to Baf. The only noteworthy difference is that the static arguments to the bootstrap method are all preceded to a bracketed type identifier, in the example (I). This is necessary to allow Jasmin to determine which kind of class constant to generate as a bytecode representation of that constant value. In the above example, I would indicate an int.
Bytecode constants of type CONSTANT_MethodType_info are not currently supported. However, those do not yet appear to be used anyway; they may become important with Java 8's support for lambda functions.
Current pitfalls include the odd argument passing to bootstrap methods. Remember that a bootstrap method always receives three implicit arguments from the virtual machine. Those arguments are of type Lookup, String, and MethodType. This does not mean, however, that one can rely on the bootstrap method's signature to start with those argument types. Instead, a bootstrap method could consume any number of those arguments through a varargs argument, as in:
CallSite bootstrap(Object caller, Object... nameAndTypeWithArgs)For this reason, Soot currently does not check the correctness of the bootstrap method's arguments against the provided arguments. Users hence have to be careful to provide a correct signature. Note that we do check, however, that the correct return type, java.lang.invoke.CallSite, is provided.
This document was generated using the LaTeX2HTML translator Version 2008 (1.71)
Copyright © 1993, 1994, 1995, 1996,
Nikos Drakos,
Computer Based Learning Unit, University of Leeds.
Copyright © 1997, 1998, 1999,
Ross Moore,
Mathematics Department, Macquarie University, Sydney.
The command line arguments were:
latex2html invokedynamic -split 0 -nonavigation -dir ./
The translation was initiated by Eric Bodden on 2012-01-22