-
Enhancement
-
Resolution: Fixed
-
P4
-
None
-
None
-
b22
Improve the handling of the java.lang.invoke.MethodHandle.TRACE_METHOD_LINKAGE property to print out the full graph of MethodHandles that are used at a CallSite. This helps us understand how invokedynamic call sites are resolved. For example:
public class StrConcat {
static String hello = "Hello";
static String world = "World";
public static void main(String args[]) {
System.out.println(hello + world);
System.out.println(hello + "World");
}
}
$ java -Djava.lang.invoke.MethodHandle.TRACE_METHOD_LINKAGE=true -cp . StrConcat
linkCallSite StrConcat.main(StrConcat.java:5) java.lang.invoke.StringConcatFactory.makeConcatWithConstants(Lookup,String,MethodType,String,Object[])CallSite/invokeStatic makeConcatWithConstants(String,String)String/BSA1=
linkMethod java.lang.invoke.MethodHandle.invokeExact(Lookup,String,MethodType,String,Object[])CallSite/5
linkMethod => java.lang.invoke.Invokers$Holder.invokeExact_MT(Object,Object,Object,Object,Object,Object,Object)Object/invokeStatic + (Lookup,String,MethodType,String,Object[])CallSite
linkCallSite target class => java.lang.invoke.BoundMethodHandle$Species_L
linkCallSite target => (String,String)String : BMH.reinvoke000_LLL_L=Lambda(a0:L/SpeciesData[L => Species_L],a1:L,a2:L)=>{
t3:L=Species_L.argL0(a0:L);
t4:L=MethodHandle.invokeBasic(t3:L,a1:L,a2:L);t4:L}
& BMH=[
0: MethodHandle = {(Object,Object)String : DMH.invokeStatic000_LLL_L=Lambda(a0:L,a1:L,a2:L)=>{
t3:L=DirectMethodHandle.internalMemberName(a0:L);
t4:L=MethodHandle.linkToStatic(a1:L,a2:L,t3:L);t4:L}
& DMH.MN=java.lang.StringConcatHelper.simpleConcat(Object,Object)String/invokeStatic
}
]
linkCallSite linkage => java.lang.invoke.Invokers$Holder.linkToTargetMethod(Object,Object,Object)Object/invokeStatic + MethodHandle(String,String)String
HelloWorld
linkCallSite StrConcat.main(StrConcat.java:6) java.lang.invoke.StringConcatFactory.makeConcatWithConstants(Lookup,String,MethodType,String,Object[])CallSite/invokeStatic makeConcatWithConstants(String)String/BSA1=World
linkCallSite target class => java.lang.invoke.BoundMethodHandle$Species_LL
linkCallSite target => (String)String : invoke000_LL_L=Lambda(a0:L/SpeciesData[LL => BoundMethodHandle$Species_LL],a1:L)=>{
t2:L=BoundMethodHandle$Species_LL.argL1(a0:L);
t3:L=BoundMethodHandle$Species_LL.argL0(a0:L);
t4:L=MethodHandle.invokeBasic(t3:L,a1:L,t2:L);t4:L}
& BMH=[
0: MethodHandle = {(Object,Object)String : DMH.invokeStatic000_LLL_L=Lambda(a0:L,a1:L,a2:L)=>{
t3:L=DirectMethodHandle.internalMemberName(a0:L);
t4:L=MethodHandle.linkToStatic(a1:L,a2:L,t3:L);t4:L}
& DMH.MN=java.lang.StringConcatHelper.simpleConcat(Object,Object)String/invokeStatic
}
1: ( World )
]
linkCallSite linkage => java.lang.invoke.Invokers$Holder.linkToTargetMethod(Object,Object)Object/invokeStatic + MethodHandle(String)String
HelloWorld
********************************************************************
By human parsing, we can see that the first call site at StrConcat.java:5 is resolved to:
MethodHandle mh = a0.argL0; // DirectMethodHandle of simpleConcat(Object,Object)
invoke mh with (a1, a2); // a1 = StrConcat.hello; a2 = StrConcat.world
return the result of the mh invocation
The second callsite is similar, except the second argument to the simpleConcat() call is taken from a0.argL1 (the constant "World").
public class StrConcat {
static String hello = "Hello";
static String world = "World";
public static void main(String args[]) {
System.out.println(hello + world);
System.out.println(hello + "World");
}
}
$ java -Djava.lang.invoke.MethodHandle.TRACE_METHOD_LINKAGE=true -cp . StrConcat
linkCallSite StrConcat.main(StrConcat.java:5) java.lang.invoke.StringConcatFactory.makeConcatWithConstants(Lookup,String,MethodType,String,Object[])CallSite/invokeStatic makeConcatWithConstants(String,String)String/BSA1=
linkMethod java.lang.invoke.MethodHandle.invokeExact(Lookup,String,MethodType,String,Object[])CallSite/5
linkMethod => java.lang.invoke.Invokers$Holder.invokeExact_MT(Object,Object,Object,Object,Object,Object,Object)Object/invokeStatic + (Lookup,String,MethodType,String,Object[])CallSite
linkCallSite target class => java.lang.invoke.BoundMethodHandle$Species_L
linkCallSite target => (String,String)String : BMH.reinvoke000_LLL_L=Lambda(a0:L/SpeciesData[L => Species_L],a1:L,a2:L)=>{
t3:L=Species_L.argL0(a0:L);
t4:L=MethodHandle.invokeBasic(t3:L,a1:L,a2:L);t4:L}
& BMH=[
0: MethodHandle = {(Object,Object)String : DMH.invokeStatic000_LLL_L=Lambda(a0:L,a1:L,a2:L)=>{
t3:L=DirectMethodHandle.internalMemberName(a0:L);
t4:L=MethodHandle.linkToStatic(a1:L,a2:L,t3:L);t4:L}
& DMH.MN=java.lang.StringConcatHelper.simpleConcat(Object,Object)String/invokeStatic
}
]
linkCallSite linkage => java.lang.invoke.Invokers$Holder.linkToTargetMethod(Object,Object,Object)Object/invokeStatic + MethodHandle(String,String)String
HelloWorld
linkCallSite StrConcat.main(StrConcat.java:6) java.lang.invoke.StringConcatFactory.makeConcatWithConstants(Lookup,String,MethodType,String,Object[])CallSite/invokeStatic makeConcatWithConstants(String)String/BSA1=World
linkCallSite target class => java.lang.invoke.BoundMethodHandle$Species_LL
linkCallSite target => (String)String : invoke000_LL_L=Lambda(a0:L/SpeciesData[LL => BoundMethodHandle$Species_LL],a1:L)=>{
t2:L=BoundMethodHandle$Species_LL.argL1(a0:L);
t3:L=BoundMethodHandle$Species_LL.argL0(a0:L);
t4:L=MethodHandle.invokeBasic(t3:L,a1:L,t2:L);t4:L}
& BMH=[
0: MethodHandle = {(Object,Object)String : DMH.invokeStatic000_LLL_L=Lambda(a0:L,a1:L,a2:L)=>{
t3:L=DirectMethodHandle.internalMemberName(a0:L);
t4:L=MethodHandle.linkToStatic(a1:L,a2:L,t3:L);t4:L}
& DMH.MN=java.lang.StringConcatHelper.simpleConcat(Object,Object)String/invokeStatic
}
1: ( World )
]
linkCallSite linkage => java.lang.invoke.Invokers$Holder.linkToTargetMethod(Object,Object)Object/invokeStatic + MethodHandle(String)String
HelloWorld
********************************************************************
By human parsing, we can see that the first call site at StrConcat.java:5 is resolved to:
MethodHandle mh = a0.argL0; // DirectMethodHandle of simpleConcat(Object,Object)
invoke mh with (a1, a2); // a1 = StrConcat.hello; a2 = StrConcat.world
return the result of the mh invocation
The second callsite is similar, except the second argument to the simpleConcat() call is taken from a0.argL1 (the constant "World").
- relates to
-
JDK-8292699 Improve printing of classes in native debugger
-
- Resolved
-