java - 为什么反编译的 java 程序并不总是可以直接编译,哪些部分不能?

标签 java decompiling decompiler

所以我试图对已编译的 Java 程序进行轻微有效的合法更改。我正在使用 JD-GUI for Mac 反编译它。大多数情况下,反编译代码没有错误,但也有一些奇怪的事情,比如未声明的变量、多个相同的变量声明和一些不容易编译的奇怪语句。 反编译后的代码中有些奇怪的语句,真是百思不得其解。我一直在使用一个 switch 语句时遇到问题:

    switch ($SWITCH_TABLE$PackageName$ClassName$InnerEnumName()[getPlatform().ordinal()])

其中 PackageName.ClassName 是该语句所在的类,InnerEnumName 是 ClassName 中的内部枚举。 还要注意 getPlatform() 是 ClassName 中的一个方法,它返回一个 InnerEnumName 类型的枚举

奇怪的是,当我将这个类从有问题的语句中剥离出来,编译它,然后将它重新插入到程序中时,它开始工作但有一些奇怪的错误。 例如,当我将 switch 语句更改为

    switch (getPlatform().ordinal())

它开始命中案例 3(第三个案例和值 3 的案例),而它应该命中案例 4(再次是第四个案例以及值 4 的案例)

最佳答案

反编译总是不完美的。反编译器必须获取字节码并对原始源代码进行逆向工程,找出循环在哪里,循环控制是什么等等。我永远不会期望它对于非平凡的程序来说是完美无缺的。

在 $ 名称的情况下,这些是在“伪造”内部类的过程中在内部生成的名称(因为 JVM 实际上并不支持内部类)。反编译器显然在弄清楚内部类是什么并适本地命名它们以及编译器创建的对象来伪造东西方面做得不完美。熟悉字节码格式的人可能会很快解决问题,但与其他人一样,这并不简单。

(在这种特殊情况下,编译器似乎出于某种原因创建了一个从内部枚举值到其他一些值的映射表,当您“剥离”该语句时,您丢失了该映射。)

[我要补充一点,反编译器的一个大问题是 javac 是一个移动的目标。特别是像内部类实现这样的东西正在不断调整,所以一周工作的东西可能会在下一个 +.001 版本的编译器下失败。]

关于java - 为什么反编译的 java 程序并不总是可以直接编译,哪些部分不能?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6932316/

相关文章:

java - Spring Reactive WebClient

java - 执行的线程仅打印一定数量的范围

java - 如何纠正这个: Content is not allowed in prolog

c++ - gcc - 如何检测基于指针的内存访问

windows - 您可以将游戏反编译为原始源代码吗?

java - 反编译JAVA DLL

java - 使用 Eclipse JD 调试 - 行不匹配

java - 类初始化后使用 Dagger 2 解决命名依赖关系

java - 如何从 gradle 任务运行 mvn 命令?

java - 这会使反编译/破解更难吗?