反汇编的 Java 类文件与 Source 不同

逆向工程 爪哇 bin-diffing
2021-06-15 19:21:18

在试图理解 TestNG 的行为时,我发现我自己反汇编了 .class 文件。在此期间,我无意中注意到官方二进制文件与从源代码和源代码本身手动构建的二进制文件不同。

我反汇编二进制文件的原因只是为了证明二进制文件确实缺少局部变量表(为了好玩),因为我无法检查局部变量。

我从标签 6.11 的项目存储库构建了源代码。使用摇篮。

首先,我检查了两者javap -l -p TestNG.class,将输出写入两个单独的文件并比较结果描述。到现在为止还挺好。

然后,为了好玩,我使用以下命令反汇编了两个类文件:

javap -c -p /tmp/TestNG.mvn.class > /tmp/TestNG.mvn.java
javap -c -p /tmp/TestNG.mine.class > /tmp/TestNG.mine.java

然后我对两者进行了区分,意外地发现私有字段m_executionListeners丢失了。

--- /tmp/TestNG.mvn.java      2017-06-03 23:12:16.005211337 +0200
+++ /tmp/TestNG.mine.java     2017-06-03 23:12:08.245208191 +0200
@@ -92,6 +92,8 @@

   protected long m_start;

+  private final java.util.Map<java.lang.Class<? extends org.testng.IExecutionListener>, org.testng.IExecutionListener> m_executionListeners;
+

(不,它的声明并没有四处走动,它已经消失了。)

所以我认为这可能是某种编译器优化。但它实际上被引用和访问了两次。这是一种访问:

public void addListener(ITestNGListener listener) {
   if (listener == null) {
     return;
   }
   if (listener instanceof ISuiteListener) {
     ISuiteListener suite = (ISuiteListener) listener;
     maybeAddListener(m_suiteListeners, suite.getClass(),  suite);
   }
   // ...
   if (listener instanceof IExecutionListener) {
     IExecutionListener execution = (IExecutionListener) listener;
     maybeAddListener(m_executionListeners, execution.getClass(), execution);
   }
   // ...
 }

查看源码

通过instanceof检查、类型转换和maybeAddListener()调用运行的所有其他字段仍然存在。

我的结论是否正确,二进制文件不是从(应该是)相关源构建的?或者这里发生了什么?

1个回答

您是正确的,二进制文件与标记的源不匹配。但是,它确实与提交6cfc6b4a403f8487d9fa96aa3d42db7848c8755a 中所做的更改相匹配,该更改是在 2 月 25 日,即最近一次标记为 6.11 的提交之后的一天和 6.11 中的最近一次合并提交之前所做的。

我只能推测,但他们的本地版本 6.11 似乎可能包含一两个额外的提交,他们不小心在 Github 上的标签中遗漏了这些提交。