如何解决我们如何通过`getClassgetName`在源文件中找到lambda的位置?
我们有一些在线日志,它们看起来像Runnable runnable = () -> {}
。
这些日志指向某些lambda函数(功能接口),例如SomeClass
,但是$package.$ClassName$$Lambda$index/$number@hashCode
具有很多lambda函数,因此需要在源文件中找到它们的特定行才能找到错误的位置
顺便说一句,我们发现,这些lambda函数的所有日志看起来都是$index/$number
,而同一lambda在重新编译类之前具有相同的disp("a :: "+string(a)+" :: b :: "+string(b)))
。
解决方法
这是不可能的。该类在运行时生成,并且不反映触发该类生成的代码位置。观察到的索引号反映了类生成的顺序,而不是代码中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,并且类名中没有任何内容暗示我们在看可运行的“偶数”还是“奇数”。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。