有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

静态重新初始化Java类

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

现在,当我们的代理启动时,一些类被初始化,特别是java。lang.ref.Reference,它启动一个线程。我们的代理使用自定义java代码插入线程启动方法,该代码由代码覆盖工具插入。 coverage工具在java代理代码中放置了一些带有静态初始值设定项的静态内部类,因此这是java的结果。lang.ref.Reference正在初始化

问题是,此时(当java.lang.ref.Reference被初始化时),JVM的一些基本功能还没有到位。具体来说,代码覆盖工具初始值设定项希望访问系统。getProperty(字符串名称),但不是系统。props仍然为null,因此调用会导致NullPointerException。 这导致代码覆盖工具的静态内部类未初始化,该类处于初始化错误状态,结果是NoClassDefFoundError。对该类的每次后续访问都会导致NoClassDefFoundError

我现在的意图是忽略这个初始初始化错误,等待VM_启动,然后将相关类的ClassState重置为“linked”。通过这种方式,我希望JVM将尝试在后续访问类时再次初始化该类

有没有人知道,如果JVMTI的经纪人能做到这一点,并给我一些建议如何做到这一点


共 (2) 个答案

  1. # 1 楼答案

    VM_启动后重新传输FormClasses将生成一个新的类加载钩子供参考,允许您在安全的VM阶段执行指令插入。。。要么重新传输引用,要么重新传输GetLoadedClass并重新传输它们

  2. # 2 楼答案

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

    因此,我建议将代码分为三类,而不是混淆本机代码和代理:

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

    对于测试,实例化模型类。重写测试所需的方法,以便返回测试代码所需的模拟数据对象(有关模拟测试的示例,请参见mockito

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