在试图理解 TestNG 的行为时,我发现我自己反汇编了 .class 文件。在此期间,我无意中注意到官方二进制文件与从源代码和源代码本身手动构建的二进制文件不同。
我反汇编二进制文件的原因只是为了证明二进制文件确实缺少局部变量表(为了好玩),因为我无法检查局部变量。
- 项目:https : //github.com/cbeust/testng.git
- 神器版本/标签:6.11
- 源文件:(
TestNG.java官方存储库) - 类文件:
TestNG.class在 testng-6.11.jar (repo.maven.apache.org) - 使用的 JDK:OpenJDK 1.8.0 131
我从标签 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()调用运行的所有其他字段仍然存在。
我的结论是否正确,二进制文件不是从(应该是)相关源构建的?或者这里发生了什么?