Background
I'm currently writing a JVM in C# for purely academic purposes (and maybe to build a mixed .NET and Java/Scala application in the future).
Context
I write the simple JAVA class:
public class test
{
public static String hello_world(int i)
{
return "Hello " + i + " World!";
}
}
And compile it into test.class
.
When I decompile it with my decompiler (which I have written as part of the JVM), I see the following instructions for this method:
iload_0
invokedynamic 2
areturn
When looking inside the constant pool for the constant at index 2
, I see an InvokeDynamic-Constant entry with the following data:
makeConcatWithConstants : (I)Ljava/lang/String;
Which makes sense, I guess (I am more a .NET-user than a JAVA-user).
When executing my method hello_world
with the parameter 1
, I have the following Stack before executing invokedynamic 2
:
----TOP---
0x00000001
--BOTTOM--
Question
My question is: How do I use invokedynamic
?
I cannot resolve the method makeConcatWithConstants
, as the InvokeDynamic-Constant does not give me any hint, where makeConcatWithConstants
might be located (see documentation).
Neither does the stack contain a reference to the heap, indicating which instance type the method makeConcatWithConstants
could be associated with.
I read through the invokedynamic
docs but I do not understand it (Maybe I'm to much "damaged" by the .NET-Framework).
Can somebody point me to some example about what is going on under the JVM's hood when executing these three instructions? (What the callee of invokedynamic
expects etc.)?
I already implemented invokestatic
in my JVM ... but I am currently unable to understand invokedynamic
.
The idea of
invokedynamic
is; When first encountering this bytecode call a bootstrap method which creates aCallsite
object that links to the actual method that needs to be invoked.In practice this often means that you dynamically create the implementation for the call.
If you look at your program with
javap -v test
, you will see at the bottom aBootstrapMethods
attribute:Where you can see that the bootstrap method for this particular callsite is located in
StringConcatFactory
The
Method arguments
are the set of constant arguments.The leading arguments of
Lookup
,String
andMethodType
are respectively; a lookup object with the same priveledges as the callsite, some name, and the type of the callsite. The first of these needs to be provided by the VM at runtime , and the latter 2 are provided by the invokedynamic constant pool entry in the form of a name and type:So to implement this bytecode you have to have some machinery in place to create the lookup object, and then be able to call the bootstrap method. After that you can call
dynamicInvoker()
on the returnedCallsite
object, which gives you aMethodHandle
that you should then cache for this particular callsite and then (finally) invoke.If you want to look at how this is implemented in OpenJDK you can find the implementation here: http://hg.openjdk.java.net/jdk/jdk/file/tip/src/hotspot/share/interpreter/bytecodeInterpreter.cpp#l2446
I'm guessing this is probably too tricky at this early stage of the project, so for now it might be easier to compile your program with
-XDstringConcat=inline
, since that uses the legacyStringBuilder
concatenation, which should be simpler to implement.