【问题标题】:Decompiling JVM languages反编译JVM语言
【发布时间】:2011-04-19 21:07:42
【问题描述】:

是否可以将 JVM 语言(如 Groovy、Scala)反编译为其初始形式?

如果我尝试反编译一个 4 行的 Groovy 类,我会得到大约 20 行反编译的 Java 代码。

这更像是一个理论问题而不是实际问题,因为市场上没有这样的反编译器(我不知道)。

谢谢。

【问题讨论】:

  • 请注意,编译器丢弃无法重构的信息,因此您将永远无法取回原始信息。

标签: java jvm reverse-engineering decompiling jvm-languages


【解决方案1】:

是的,Java 反编译器可以管理类似的保真度(意思是:代码看起来相似,但不一定相同)。

但是,对于每种语言,您都需要一个专用的反编译器。

编辑:我想我需要澄清我期望的保真度水平:

  • 局部变量的名称可能是可重现的,也可能是不可重现的
  • 循环类型可能被错误解释(for 替换为 while,...)
  • 更笼统地说:可以通过两种类似方式完成的事情可能会被误解
  • ...

所有这些都是反编译 Java 代码时也会出现的错误,仅仅是因为字节码与 Java 源代码的关联不是 1:1。

但是,如果您有一个专用的 Groovy 反编译器,那么我强烈怀疑它通过反编译已编译的 Groovy 代码产生的可读代码比 Java 反编译器要多得多。

【讨论】:

  • 确实是一个非常乐观的假设。
  • @Ingo:我不明白这是多么乐观。由合格的 Java 反编译器生成的代码也仅与原始源代码具有基本相似性。局部变量名称通常会丢失(除非在编译期间明确包含在 .class 文件中),并且通常使用的特定循环类型也被错误表示(用 while 循环替换 for 循环)。
  • 我在帖子中阐述了我的不同意见。
  • @Ingo:我认为我们的意见并没有太大的不同。我只是将这个问题解释为“专用的 Groovy 反编译器能像专用的 Java 反编译器一样有用吗?”,对此我说:“是的,它同样没用”;-)
【解决方案2】:

这不一定是可能的。例如,一种语言可以以一种不可逆的方式破坏它的名称。此外,它可以将源语言的不同结构映射到单个 java 语言结构。

然而,最重要的是,Java 语言(相对于 JVM 字节码)无法强大到能够以可以具体化的方式对源语言的某些概念或结构进行编码。 Java 和 JVM 字节码已经是这种情况,后者无法表达泛型。

【讨论】:

  • 对于第二点,我并不是要将 Groovy 生成的 Java 字节码转换回 Java,而是转换回 Groovy。
  • @Alexandru - 这正是我的观点 - 我不了解 Groovy,但可以想象它具有某些无法在不丢失信息的情况下编译为字节码的功能。具有讽刺意味的是,在编译为字节码时会丢失信息的语言的一个示例是 Java 本身,因此可以肯定地假设其他语言会更是如此。
【解决方案3】:

嗯,我唯一能想到的就是编译器优化和 cmets 的问题。注释不会保留在字节码中(谢天谢地),编译器可能会更改源代码以获得更好的性能,此外这似乎是可能的。

【讨论】:

  • 我不担心 cmets。但是你要如何恢复这样的东西呢? this.metaClass = ((MetaClass)ScriptBytecodeAdapter.castToType(tmp12_9, $get$$class$groovy$lang$MetaClass())); tmp12_9;而(真)返回;
  • @Alexandru:那不是字节码。这就是 Java 语言反编译器 试图解释不是通过编译 Java 语言代码产生的字节码的方式。这必然会产生奇怪的结果,但正确语言的专用反编译器会识别“奇怪”的字节码结构并知道它代表什么语言结构。
  • @Joachim,你说得对,这不是字节码,这就是我没有说它的原因。我想这是有道理的,如果你知道你正在处理一个 Groovy 生成的类文件,你应该知道你必须以不同于 Java 生成的类文件的方式处理它。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2010-11-16
  • 2010-12-24
  • 2020-09-03
  • 1970-01-01
  • 2011-03-16
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多