我们有一些在线日志,它们看起来像com.xxx.yyy.SomeClass$$Lambda$12345/7654321@qwert
。这些日志指向像Runnable runnable = () -> {}
这样的lambda函数(函数接口),但是SomeClass
有很多lambda函数,所以需要在源文件中找到它们的特定行,以便定位错误。
顺便说一句,我们已经弄清楚的是,所有这些lambda函数的日志看起来都是$package.$ClassName$$Lambda$index/$number@hashCode
的,并且相同的lambda在类重新编译之前具有相同的$index/$number
。
发布于 2020-11-11 08:20:23
这是不可能的。该类是在运行时生成的,并不反映触发类生成的代码位置。观察到的索引号反映了类生成的顺序,而不是代码中lambda表达式的外观。
只要程序的行为没有改变,它可能看起来在这个数字和代码位置之间有一个稳定的映射,但是我们可以很容易地通过创建一个故意改变其行为的程序来反驳这一点:
import java.io.IOException;
import java.lang.invoke.MethodHandles;
import java.nio.file.Paths;
public class LambdaClassGeneration {
public static void main(String[] args) {
if(args.length == 0) {
runMyself();
return;
}
boolean even = args[0].equals("even");
for(int i = 0; i < 2; i++, even = !even) {
Runnable r;
StackTraceElement e;
if(even) {
r = () -> System.out.println("even");
e = new Exception().getStackTrace()[0];
}
else {
r = () -> System.out.println("odd");
e = new Exception().getStackTrace()[0];
}
r.run();
System.out.println("created at "+e);
System.out.println(r.getClass());
}
}
private static void runMyself() {
String[] cmd = {
Paths.get(System.getProperty("java.home"), "bin", "java").toString(),
"-cp", System.getProperty("java.class.path"),
MethodHandles.lookup().lookupClass().getName(),
"arg"
};
ProcessBuilder p = new ProcessBuilder().inheritIO();
for(int i = 0; i < 2; i++) try {
System.out.println("Run " + i);
cmd[cmd.length-1] = i%2 == 0? "even": "odd";
p.command(cmd).start().waitFor();
System.out.println();
}
catch(IOException | InterruptedException ex) {
ex.printStackTrace();
return;
}
}
}
该程序使用不同的参数"even"
和"odd"
运行两次,以显示不同的行为,从而影响Runnable
实现的对象在运行时对lambda表达式求值的顺序。
它打印如下内容:
Run 0
even
created at LambdaClassGeneration.main(LambdaClassGeneration.java:20)
class LambdaClassGeneration$$Lambda$1/0x0000000800b90840
odd
created at LambdaClassGeneration.main(LambdaClassGeneration.java:24)
class LambdaClassGeneration$$Lambda$2/0x0000000800b91440
Run 1
odd
created at LambdaClassGeneration.main(LambdaClassGeneration.java:24)
class LambdaClassGeneration$$Lambda$1/0x0000000800b90840
even
created at LambdaClassGeneration.main(LambdaClassGeneration.java:20)
class LambdaClassGeneration$$Lambda$2/0x0000000800b91440
清楚地表明,第一个生成的类得到索引1,第二个生成的类得到索引2,并且类名中没有任何东西暗示我们正在查看的是“偶数”还是“奇数”可运行的。
https://stackoverflow.com/questions/64780063
复制