Skip to content

Instantly share code, notes, and snippets.

@amaembo
Created July 21, 2021 17:08
Show Gist options
  • 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();
}
@amaembo
Copy link
Author

amaembo commented Aug 7, 2021

And yet I wonder: is this the right trade off?

Probably not, but I don't feel I have enough energy to persuade JDK folks to accept this. In any case, turning this into a proper JDK patch will require too much time and energy. I'm not against if somebody else will do this :-)

Likewise, an inner class can be a static inner class, or not

This part is under active investigation now, see openjdk/jdk#4966 for details.

@Markvy
Copy link

Markvy commented Aug 9, 2021

Re: static inner classes: this is amazing, I thought it would literally never get fixed. Thanks for the link!
Re: energy to persuade: maybe everyone will just love this idea and no persuasion will be needed?

@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