此代码如何使用保留的关键字作为字段名称?

The*_*uck 2 java bytecode jvm-bytecode

尝试对服务器应用程序启动进行故障排除时,我在旧版Java字节码中发现以下构造。我的IDE反编译了一些第三方库,我很好奇它的有效性-从来没有见过关键字 可以用作字节码中的字段名称。

字节码版本为48.0(Java 1.4)。

public final class f implements UserContext{

private final String try;
private final UserInfo do;

// a lot of code here 

public UserInfo getUserInfo(){
    return this.do;
}

public String getViewName(){
    return this.try;
}

}
Run Code Online (Sandbox Code Playgroud)

好像该库是使用一些混淆功能进行编译的,但是如何在JVM级别上呢?是否允许在JVM启动时没有特殊标志?

更新:该UserInfo字段的正确getter名称是getUserInfo-很抱歉使每个人都对具有不同返回值的方法的模棱两可的命名感到困惑,这是一个复制粘贴问题,因为代码位于没有直接访问该站点的远程计算机上。

Joa*_*uer 5

Java虚拟机规范(负责定义字节码的外观)对事物名称没有与关键字相关的约束。

这些约束仅存在于Java 语言级别。您使用的字节码不会反编译为有效的Java,因为它使用的名称在Java语言中无效,但对JVM有效。

两种相似的逻辑适用于两个getViewName仅在返回类型上有所不同的方法:JVM规范在字节码中允许这样做(并且工作得很好),但是Java语言规范禁止这样做。

像这样的字节码的最常见原因是Java代码被编译为字节码,然后被混淆。

另一个可能的原因是该代码最初不是通过编译Java代码生成的,而是针对JVM的另一种语言。在这种情况下,这种情况不太可能发生,因为do在应该保留视图名称的情况下,没人会命名变量。

  • …并且混淆工具的作者缺乏创造力,甚至无法提出更糟糕的结果。请注意,在字节码级别上,即使字段仍可以通过类型区分也可以具有相同的名称。同样,甚至不需要名称来构成单词,换行符也将是有效名称,字段名称也可能是“ a + 1”(在同时具有变量“ a”和“ a + 2”时尤其有趣。另请参见[this answer](/sf/answers/2135161661/)。顺便说一句,自Java 5起,编译器可能会生成仅在返回类型上有所不同的桥方法。 (2认同)