我在尝试对服务器应用程序启动进行故障排除时在遗留的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;
}
}
似乎该库是使用一些混淆功能编译的, 但是它怎么可能在 JVM 级别? 没有特殊允许吗 JVM启动的标志?
更新:UserInfo
字段的正确 getter 名称是getUserInfo
- 很抱歉让每个人都对具有不同返回值的方法的模糊命名感到困惑,这是一个复制粘贴问题,因为代码位于远程机器上没有直接访问站点。
Java 虚拟机规范(负责定义字节码的外观(对事物名称没有与关键字相关的约束。
这些约束仅存在于 Java语言级别。您使用的字节码不会反编译为有效的 Java,因为它使用的名称在 Java 语言中无效,但对 JVM有效。
类似的逻辑适用于仅在返回类型上不同的两种getViewName
方法: JVM规范允许(并且工作正常(,但Java语言规范禁止这样做。
像这样的字节码最常见的原因是Java代码被编译为字节码,然后被混淆。
另一个可能的原因是,代码最初不是通过编译Java代码生成的,而是另一种针对JVM的语言。在这种情况下,这不太可能,因为没有人会在应该保存视图名称时do
命名变量。
我几乎认为代码被混淆了,但随后您也会在方法名称中看到它。有时混淆器会执行语言中不允许的事情,因此当您反编译它们时,您无法重新编译源代码。只有Java语法不允许do
或try
作为变量名,JVM(以及在JVM上运行的其他语言(并不关心它。
这要么是故意混淆,要么它们不是从 Java 类编译的。
这可能是某种形式的混淆。
字符串try
也许可以trу
。它们实际上是不同的。剪切并粘贴第一个,它将被视为保留关键字try
。剪切并粘贴第二个,它将是一个有效的字段名称。第二种情况下的y
不是正常的y
。这是一个不同的 unicode 字符。
不能将关键字用作变量名,请参阅 Java 语言规范中的第 3.9 章。
反编译器给了你错误/错误的代码。