Skip to content

Instantly share code, notes, and snippets.

@amaembo
Created July 21, 2021 17:08
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 1 You must be signed in to fork a gist
  • Save amaembo/40c57d7dd423441e9673653f15e76c9d to your computer and use it in GitHub Desktop.
Save amaembo/40c57d7dd423441e9673653f15e76c9d to your computer and use it in GitHub Desktop.
Patch for InnerClassLambdaMetafactory to generate line number debug info
diff --git a/src/java.base/share/classes/java/lang/invoke/InnerClassLambdaMetafactory.java b/src/java.base/share/classes/java/lang/invoke/InnerClassLambdaMetafactory.java
--- a/src/java.base/share/classes/java/lang/invoke/InnerClassLambdaMetafactory.java (revision 57611b30219191160f7faccb811b41a31c25c0b8)
+++ b/src/java.base/share/classes/java/lang/invoke/InnerClassLambdaMetafactory.java (date 1626887157914)
@@ -315,6 +315,18 @@
return generateInnerClass();
}
+ private static StackTraceElement getCallerFrame() {
+ StackTraceElement[] trace = new Exception().getStackTrace();
+ for (int i = 0; i < trace.length - 1; i++) {
+ StackTraceElement ste = trace[i];
+ if (ste.getClassName().equals("java.lang.invoke.MethodHandleNatives") &&
+ ste.getMethodName().equals("linkCallSite")) {
+ return trace[i + 1];
+ }
+ }
+ return null;
+ }
+
/**
* Generate a class file which implements the functional
* interface, define and return the class.
@@ -344,6 +356,14 @@
cw.visit(CLASSFILE_VERSION, ACC_SUPER + ACC_FINAL + ACC_SYNTHETIC,
lambdaClassName, null,
JAVA_LANG_OBJECT, interfaceNames);
+ int lineNumber;
+ StackTraceElement ste = getCallerFrame();
+ if (ste != null) {
+ cw.visitSource(ste.getFileName(), null);
+ lineNumber = ste.getLineNumber();
+ } else {
+ lineNumber = -1;
+ }
// Generate final fields to be filled in by constructor
for (int i = 0; i < argDescs.length; i++) {
@@ -363,14 +383,14 @@
// Forward the SAM method
MethodVisitor mv = cw.visitMethod(ACC_PUBLIC, interfaceMethodName,
interfaceMethodType.toMethodDescriptorString(), null, null);
- new ForwardingMethodGenerator(mv).generate(interfaceMethodType);
+ new ForwardingMethodGenerator(mv, lineNumber).generate(interfaceMethodType);
// Forward the altMethods
if (altMethods != null) {
for (MethodType mt : altMethods) {
mv = cw.visitMethod(ACC_PUBLIC, interfaceMethodName,
mt.toMethodDescriptorString(), null, null);
- new ForwardingMethodGenerator(mv).generate(mt);
+ new ForwardingMethodGenerator(mv, lineNumber).generate(mt);
}
}
@@ -541,14 +561,19 @@
* method, converting arguments, as needed.
*/
private class ForwardingMethodGenerator extends TypeConvertingMethodAdapter {
+ private final int lineNumber;
- ForwardingMethodGenerator(MethodVisitor mv) {
+ ForwardingMethodGenerator(MethodVisitor mv, int lineNumber) {
super(mv);
+ this.lineNumber = lineNumber;
}
void generate(MethodType methodType) {
visitCode();
+ Label start = new Label();
+ visitLabel(start);
+
if (implKind == MethodHandleInfo.REF_newInvokeSpecial) {
visitTypeInsn(NEW, implMethodClassName);
visitInsn(DUP);
@@ -585,6 +610,9 @@
visitInsn(getReturnOpcode(samReturnClass));
// Maxs computed by ClassWriter.COMPUTE_MAXS,these arguments ignored
visitMaxs(-1, -1);
+ if (lineNumber >= 0) {
+ visitLineNumber(lineNumber, start);
+ }
visitEnd();
}
@Markvy
Copy link

Markvy commented Aug 15, 2021

Do you mind if I post your article to the JDK mailing list?

@amaembo
Copy link
Author

amaembo commented Aug 15, 2021

It's up to you.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment