8295537: Enhance TRACE_METHOD_LINKAGE to show the target MethodHandle
Reviewed-by: jvernee, redestad, mchung
This commit is contained in:
parent
182c215888
commit
fd668dc44f
src/java.base/share/classes/java/lang/invoke
@ -158,21 +158,29 @@ abstract non-sealed class BoundMethodHandle extends MethodHandle {
|
||||
final int fieldCount() { return speciesData().fieldCount(); }
|
||||
|
||||
@Override
|
||||
Object internalProperties() {
|
||||
return "\n& BMH="+internalValues();
|
||||
Object internalProperties(int indentLevel) {
|
||||
return "\n" + debugPrefix(indentLevel) + "& BMH=" + internalValues(indentLevel);
|
||||
}
|
||||
|
||||
@Override
|
||||
final String internalValues() {
|
||||
final String internalValues(int indentLevel) {
|
||||
String prefix = debugPrefix(indentLevel);
|
||||
int count = fieldCount();
|
||||
if (count == 1) {
|
||||
if (count == 1 && indentLevel < 0) {
|
||||
return "[" + arg(0) + "]";
|
||||
}
|
||||
StringBuilder sb = new StringBuilder("[");
|
||||
for (int i = 0; i < count; ++i) {
|
||||
sb.append("\n ").append(i).append(": ( ").append(arg(i)).append(" )");
|
||||
Object theArg = arg(i);
|
||||
sb.append("\n ").append(prefix).append(i);
|
||||
if (indentLevel >= 0 && theArg instanceof MethodHandle) {
|
||||
sb.append(": MethodHandle = {").append(((MethodHandle)theArg).debugString(indentLevel+1));
|
||||
sb.append("\n ").append(prefix).append("}");
|
||||
} else {
|
||||
sb.append(": ( ").append(theArg).append(" )");
|
||||
}
|
||||
}
|
||||
return sb.append("\n]").toString();
|
||||
return sb.append("\n").append(prefix).append("]").toString();
|
||||
}
|
||||
|
||||
/*non-public*/
|
||||
|
@ -170,8 +170,8 @@ sealed class DirectMethodHandle extends MethodHandle {
|
||||
}
|
||||
|
||||
@Override
|
||||
String internalProperties() {
|
||||
return "\n& DMH.MN="+internalMemberName();
|
||||
String internalProperties(int indentLevel) {
|
||||
return "\n" + debugPrefix(indentLevel) + "& DMH.MN=" + internalMemberName();
|
||||
}
|
||||
|
||||
//// Implementation methods.
|
||||
|
@ -1029,12 +1029,18 @@ class LambdaForm {
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
return debugString(-1);
|
||||
}
|
||||
|
||||
String debugString(int indentLevel) {
|
||||
String prefix = MethodHandle.debugPrefix(indentLevel);
|
||||
String lambdaName = lambdaName();
|
||||
StringBuilder buf = new StringBuilder(lambdaName + "=Lambda(");
|
||||
StringBuilder buf = new StringBuilder(lambdaName);
|
||||
buf.append("=Lambda(");
|
||||
for (int i = 0; i < names.length; i++) {
|
||||
if (i == arity) buf.append(")=>{");
|
||||
Name n = names[i];
|
||||
if (i >= arity) buf.append("\n ");
|
||||
if (i >= arity) buf.append("\n ").append(prefix);
|
||||
buf.append(n.paramString());
|
||||
if (i < arity) {
|
||||
if (i+1 < arity) buf.append(",");
|
||||
|
@ -1688,9 +1688,19 @@ assertEquals("[three, thee, tee]", asListFix.invoke((Object)argv).toString());
|
||||
}
|
||||
/** Return a string with a several lines describing the method handle structure.
|
||||
* This string would be suitable for display in an IDE debugger.
|
||||
* @param indentLevel If negative, return only information about this MethodHandle.
|
||||
* Otherwise, return information about this MethodHandle and (recursively) all other
|
||||
* MethodHandles, if any, that are invoked directly or indirectly by this MethodHandle.
|
||||
* During the recursion, `indentLevel` is incremented (see
|
||||
* BoundMethodHandle.internalValues()) to improve readability of
|
||||
* the nested structure.
|
||||
*/
|
||||
String debugString(int indentLevel) {
|
||||
return type + " : " + internalForm().debugString(indentLevel) +
|
||||
internalProperties(indentLevel);
|
||||
}
|
||||
String debugString() {
|
||||
return type+" : "+internalForm()+internalProperties();
|
||||
return debugString(-1);
|
||||
}
|
||||
|
||||
//// Implementation methods.
|
||||
@ -1787,12 +1797,29 @@ assertEquals("[three, thee, tee]", asListFix.invoke((Object)argv).toString());
|
||||
}
|
||||
|
||||
/*non-public*/
|
||||
Object internalValues() {
|
||||
Object internalValues(int indentLevel) {
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Various debugging methods in MethodHandle (and subclasses thereof) and LambdaForm
|
||||
* take an `indentLevel` argument, so that {@link java.lang.invoke.MethodHandle.debugString(int)}
|
||||
* can return nested structures in a readable fashion. This method returns a string to be
|
||||
* prepended to each line at the specified level.
|
||||
*/
|
||||
static String debugPrefix(int indentLevel) {
|
||||
if (indentLevel <= 0) {
|
||||
return "";
|
||||
}
|
||||
return " ".repeat(indentLevel);
|
||||
}
|
||||
|
||||
/*non-public*/
|
||||
Object internalProperties() {
|
||||
return internalProperties(-1);
|
||||
}
|
||||
|
||||
Object internalProperties(int indentLevel) {
|
||||
// Override to something to follow this.form, like "\n& FOO=bar"
|
||||
return "";
|
||||
}
|
||||
|
@ -281,6 +281,12 @@ class MethodHandleNatives {
|
||||
type,
|
||||
staticArguments,
|
||||
caller);
|
||||
if (TRACE_METHOD_LINKAGE) {
|
||||
MethodHandle target = callSite.getTarget();
|
||||
System.out.println("linkCallSite target class => " + target.getClass().getName());
|
||||
System.out.println("linkCallSite target => " + target.debugString(0));
|
||||
}
|
||||
|
||||
if (callSite instanceof ConstantCallSite) {
|
||||
appendixResult[0] = callSite.dynamicInvoker();
|
||||
return Invokers.linkToTargetMethod(type);
|
||||
@ -298,13 +304,13 @@ class MethodHandleNatives {
|
||||
Object bsmReference = bootstrapMethod.internalMemberName();
|
||||
if (bsmReference == null) bsmReference = bootstrapMethod;
|
||||
String staticArglist = staticArglistForTrace(staticArguments);
|
||||
System.out.println("linkCallSite "+caller.getName()+" "+
|
||||
System.out.println("linkCallSite "+getCallerInfo(caller)+" "+
|
||||
bsmReference+" "+
|
||||
name+type+"/"+staticArglist);
|
||||
try {
|
||||
MemberName res = linkCallSiteImpl(caller, bootstrapMethod, name, type,
|
||||
staticArguments, appendixResult);
|
||||
System.out.println("linkCallSite => "+res+" + "+appendixResult[0]);
|
||||
System.out.println("linkCallSite linkage => "+res+" + "+appendixResult[0]);
|
||||
return res;
|
||||
} catch (Throwable ex) {
|
||||
ex.printStackTrace(); // print now in case exception is swallowed
|
||||
@ -313,6 +319,20 @@ class MethodHandleNatives {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a human-readable description of the caller. Something like
|
||||
* "java.base/java.security.Security.<clinit>(Security.java:82)"
|
||||
*/
|
||||
private static String getCallerInfo(Class<?> caller) {
|
||||
for (StackTraceElement e : Thread.currentThread().getStackTrace()) {
|
||||
if (e.getClassName().equals(caller.getName())) {
|
||||
return e.toString();
|
||||
}
|
||||
}
|
||||
// fallback if the caller is somehow missing from the stack.
|
||||
return caller.getName();
|
||||
}
|
||||
|
||||
// this implements the upcall from the JVM, MethodHandleNatives.linkDynamicConstant:
|
||||
static Object linkDynamicConstant(Object callerObj,
|
||||
Object bootstrapMethodObj,
|
||||
|
Loading…
x
Reference in New Issue
Block a user