1

我们正在开发一个 JVMTI Java 代理,它用于检测 java 类文件。其中一小部分(显然)是本机 C++ 代码,但大部分是 Java 代码,它通过网络加载并从本机代理代码调用。我们使用代码覆盖率工具来收集 java 部分的测试覆盖率,该部分执行源代码检测。

现在,当我们的代理启动时,一些类被初始化,特别是 java.lang.ref.Reference,它启动了一个线程。我们的代理使用自定义 java 代码检测线程启动方法,该代码由代码覆盖工具检测。覆盖工具在我们的 java 代理代码中放置了一些带有静态初始化器的静态内部类,因此这是由于 java.lang.ref.Reference 被初始化而执行的。

问题是,此时(当 java.lang.ref.Reference 被初始化时),JVM 的一些基本功能还没有到位。具体来说,代码覆盖工具初始化程序想要访问 System.getProperty(String name),但 System.props 仍然为 null,因此调用会导致 NullPointerException。这导致代码覆盖工具的静态内部类未初始化,类处于initialization_error状态,结果为NoClassDefFoundError。对此类的每次后续访问都会导致 NoClassDefFoundError。

我现在的意图是忽略这个初始初始化错误,等到 VM_Start 然后将相关类的 ClassState 重置为“链接”。这样我希望JVM在后续访问该类时会尝试再次初始化该类。

有没有人知道,如果这可以从 JVMTI 代理完成,并给我一些建议如何做到这一点?

4

2 回答 2

0

从您的描述中,我感觉您的代码耦合得太紧了。您真正想要的是在开始测试之前拥有一个已初始化的 Java VM。

因此,我建议不要将本机代码和代理搞乱,而是将代码分成三个类:

  • 抽象基类中的 Java 代码
  • 扩展基类并使用本机 C++ 代码实现抽象方法的类。理想情况下,此类不应包含除本机方法声明之外的任何 Java 代码。
  • null一个用于测试的模型类,它定义了具有空主体(或仅返回)的相同方法。

对于测试,实例化模型类。覆盖测试所需的方法,以便您可以返回被测代码所需的模拟数据对象(有关模拟测试的一些示例,请参见mockito )

或者,在测试用例中测试 Java 加载代码。在所有其他测试中,将该类添加到您的类路径并像往常一样实例化它。

于 2011-03-15T12:57:53.363 回答
0

VM_Start 之后的 RetransformClasses 将为 Reference 生成一个新的类加载钩子,允许您在安全的 VM 阶段进行检测……只需重新转换 Reference 或 getLoadedClasses 并重新转换它们。

于 2011-03-15T13:21:30.077 回答