javac生成的$$中的$$是什么意思? [英] What does $$ in javac generated name mean?

查看:149
本文介绍了javac生成的$$中的$$是什么意思?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

当转移由DependencyFinder和java-callgraph等库生成的java调用图时,我发现java编译器为匿名函数,内部类等生成名称。

When shifting through java call graph generated by libraries like DependencyFinder and java-callgraph, I found out that java compiler generate names for anonymous functions, inner classes, etc.

我已经发现了其中几个的含义(如果我错了,请更正):

I've found out the meaning of a couple of them (please correct if I'm wrong):


  • org.example.Bar $ Foo 引用 Foo ,这是 org.example.Bar的内部类

  • org.example.Bar $ 1 是指在其中一个方法中声明的匿名类code> org.example.Bar 。

  • org.example.Bar.lambda $ spam $ 1()指的是在 org.example.Bar.spam()方法中声明的lambda。

  • org.example.Bar$Foo refers to Foo, which is an inner class of org.example.Bar.
  • org.example.Bar$1 refers to an anonymous class declared inside one of the methods of org.example.Bar.
  • org.example.Bar.lambda$spam$1() refers to a lambda declared inside of org.example.Bar.spam() method.

但是,我还发现:


  1. org.example.Bar $$ Lambda $ 2.args $ 1

  2. org.example.Bar $$ Lambda $ 2.call()

  3. org.example.Bar $$ Lambda $ 7.lambdaFactory $()

  4. org.example.Bar $$ Lambda $ 7.get $ Lambda()

  1. org.example.Bar$$Lambda$2.args$1
  2. org.example.Bar$$Lambda$2.call()
  3. org.example.Bar$$Lambda$7.lambdaFactory$()
  4. org.example.Bar$$Lambda$7.get$Lambda()

上面的四个名字是指什么?双美元( $$ )是什么意思?

What does the four name above refer to? What does double dollar ($$) mean?

推荐答案

这些课程对于lambda表达式,不是生成 javac ,而是由JRE在运行时创建的。他们的名字完全没有指定,你不能依赖任何命名方案。

The classes for lambda expressions are not javac generated, but created at runtime by the JRE. Their names are completely unspecified and you can’t rely on any naming scheme.

但显然,甲骨文目前的JRE有一个可识别的模式。它将 $$ Lambda $ n 附加到定义类的名称,而 n 是一个递增的数字,它反映了运行时创建顺序,而不是编译代码的任何属性。

But obviously, Oracle’s current JRE has a recognizable pattern. It appends $$Lambda$n to the name of the defining class whereas n is an increasing number, which reflects the creation order at runtime, rather than any property of the compiled code.

您可以使用以下程序验证:

You can verify this with the following program:

public class Test {
    public static void main(String... args) {
        if(args.length==0) {
            final boolean meFirst = Math.random()<0.5;
            if(meFirst) {
                Runnable r=Test::main;
                System.out.println("first run:\t"+r.getClass());
            }
            main("second run");
            if(!meFirst) {
                Runnable r=Test::main;
                System.out.println("first run:\t"+r.getClass());
            }
        }
        else {
            Runnable r=Test::main;
            System.out.println(args[0]+":\t"+r.getClass());
            if(args[0].equals("second run")) main("last run");
        }
    }
}

取决于状态随机 meFirst 标志,它将打印

Depending on the state of the random meFirst flag, it will print either

first run:  class Test$$Lambda$1
second run: class Test$$Lambda$2
last run:   class Test$$Lambda$2

second run: class Test$$Lambda$1
last run:   class Test$$Lambda$1
first run:  class Test$$Lambda$2

它表明第一个生成的类总是得到数字 1 ,无论它是否是实例化的前两个方法引用之一在第一个 main 调用或第三个方法引用中,在第一次递归中实例化。此外,第3次执行总是遇到与第2次相同的类,因为它是相同的方法引用表达式(注意:distinct expression ,因为所有表达式的目标是相同的)并且类是重新使用。

It shows that the first generated class always gets the number 1, regardless of whether it’s one of the first two method references instantiated in the first main invocation or the third method reference, instantiated in the first recursion. Further, the 3rd execution always encounters the same class as the 2nd, as it’s the same method reference expression (note: distinct expression, as the target of all expressions is the same) and the class is re-used.

根据版本的不同,您可能会在名称后面看到类似 / number 的内容,提示名称确实无关紧要,因为这些类中的每一个都有另一个唯一标识符(它们被称为匿名类,您无法通过 ClassLoader 和名称找到它们)。

Depending on the version, you may further see something like /number appended to the names, which hints that the names really don’t matter, as each of these classes has another unique identifier (they are so called "anonymous classes" which you can’t locate via ClassLoader and name).

这些类中的字段名称如 args $ n 表示第n个捕获值。自 LambdaMetafactory 不知道捕获变量的实际名称,除了生成这样的名称之外别无选择。

Field names like args$n within these classes represent the n’th captured value. Since the LambdaMetafactory has no knowledge about the actual names of the captured variables, it has no other choice but to generate such names.

但如上所述,这是一个实现工件。只要为每个定义类中的每个创建站点生成一个新类,就可以维护这样的命名模式。但由于规范允许任意共享/重用表示等效lambda表达式(执行相同操作)和方法引用(针对相同方法)的类和实例,因此每种实现策略都无法实现这样的命名模式。

But as said, that’s an implementation artifact. It’s possible to maintain such a naming pattern, as long as a new class is generated for each creation site in each defining class. But since the specification allows arbitrary sharing/reusing of classes and instances representing equivalent lambda expressions (doing the same) and method references (targeting the same method), such a naming pattern is not possible with every implementation strategy.

这篇关于javac生成的$$中的$$是什么意思?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆