You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

OpenJ9中调用DestroyJavaVM()失败的问题求助

C/C++嵌入JVM时DestroyJavaVM()调用失败导致无法重启虚拟机

问题描述

在Windows环境下通过JNI在C/C++程序中嵌入JVM时,虚拟机初始化、启动流程均正常,但调用DestroyJavaVM()关闭虚拟机时返回-1错误,导致后续无法正常连续启动JVM。目前怀疑该问题是OpenJ9虚拟机特有的,正在测试其他JVM(如HotSpot)进行验证。

可复现代码

以下是基于Catch1.x编写的最小复现示例,仅依赖JNI头文件,配置正确JAVA_HOME后即可在Windows环境编译运行:

#define CATCH_CONFIG_MAIN
#include "catch.hpp"

#pragma once
#pragma warning( push )
#pragma warning( suppress : 26451 )
#pragma warning( suppress : 26495 )
#pragma warning( suppress : 26812 )
#include <jni.h>
#pragma warning( pop )

using create_java_vm_t = jint(JNICALL*)(JavaVM**, void**, void*);

TEST_CASE("a minimum example for the internet", "[paljni]")
{
    // 加载JVM函数
    static create_java_vm_t create_java_vm = nullptr;
    if (!create_java_vm)
    {
        auto path = std::string(getenv("JAVA_HOME")) + "bin/default/jvm.dll";

        auto dll = LoadLibrary(path.c_str());
        REQUIRE(dll);

        create_java_vm = reinterpret_cast<create_java_vm_t>(GetProcAddress(dll, "JNI_CreateJavaVM"));

        REQUIRE(nullptr != create_java_vm);
    }

    // 初始化JVM启动参数
    JavaVMInitArgs args = {};
    args.version = JNI_VERSION_1_6;

    std::vector<JavaVMOption> options;
    options.emplace(options.end())->optionString = "-verbose:init"; // 输出初始化日志,显示线程似乎已正常关闭

    args.options = options.data();
    args.nOptions = options.size();

    // 创建JVM
    JavaVM* jvm;
    JNIEnv* env;
    const auto create_ret = create_java_vm(&jvm, (void**)&env, &args);
    REQUIRE(JNI_OK == create_ret);

    // 销毁JVM - 此处返回-1,执行失败
    const auto done = jvm->DestroyJavaVM();
    REQUIRE(JNI_OK == done);

    FAIL("The test doesn't reach this point");
}

可能的原因与调试建议

  • 线程调用限制:DestroyJavaVM()必须在最初启动JVM的线程中调用,跨线程调用会直接返回失败。确保销毁操作和启动操作在同一个线程执行。
  • JNI引用泄漏:未释放的全局引用、局部引用会阻止JVM销毁。调用DestroyJavaVM()前,通过env->DeleteLocalRef()清理所有局部引用,检查全局引用是否全部通过env->DeleteGlobalRef()释放。
  • OpenJ9特定逻辑:OpenJ9对JVM销毁的资源清理、线程终止逻辑与HotSpot存在差异,可能存在未完全终止的后台守护线程或残留资源。可切换到HotSpot测试对比,确认问题是否与虚拟机实现相关。
  • 启用调试日志:打开-verbose:jni、-Xcheck:jni:warn参数,查看JNI调用的详细日志,排查是否有非法引用或未处理的资源。

内容的提问来源于stack exchange,提问作者pal

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.24 14:45:42