微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

我们如何通过`getClassgetName`在源文件中找到lambda的位置?

如何解决我们如何通过`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 举报,一经查实,本站将立刻删除。

相关推荐


Selenium Web驱动程序和Java。元素在(x,y)点处不可单击。其他元素将获得点击?
Python-如何使用点“。” 访问字典成员?
Java 字符串是不可变的。到底是什么意思?
Java中的“ final”关键字如何工作?(我仍然可以修改对象。)
“loop:”在Java代码中。这是什么,为什么要编译?
java.lang.ClassNotFoundException:sun.jdbc.odbc.JdbcOdbcDriver发生异常。为什么?
这是用Java进行XML解析的最佳库。
Java的PriorityQueue的内置迭代器不会以任何特定顺序遍历数据结构。为什么?
如何在Java中聆听按键时移动图像。
Java“Program to an interface”。这是什么意思?