从 JVM 清除所有加载的 类

Clearing all loaded classes from the JVM

我通过 JNI 创建了一个 JVM,如下所示:

bool JavaVM_Create(Jvm* &ptr, int argc, const char* argv[])
{
    bool result = false;
    if (!ptr && argc > 0)
    {
        ptr = new Jvm();
        JavaVMInitArgs jvm_args;
        JavaVMOption* options = new JavaVMOption[argc];

        for (int i = 0; i < argc; ++i)
        {
            options[i].optionString = const_cast<char*>(argv[i]);
        }

        JNI_GetDefaultJavaVMInitArgs(&jvm_args);

        jvm_args.version = JNI_VERSION_1_8;
        jvm_args.nOptions = 2;
        jvm_args.options = options;
        jvm_args.ignoreUnrecognized = false;

        result = true;

        jint num_vms = 0;
        JavaVM* vms[5] = {0};
        if (JNI_GetCreatedJavaVMs(vms, 5, &num_vms) == JNI_OK)
        {
            if (num_vms > 0)
            {
                ptr->vm = vms[0];
                ptr->vm->AttachCurrentThread();
                delete[] options;
                return result;
            }
        }

        if (!ptr->createJVM(&jvm_args))
        {
            result = false;
        }
        delete[] options;
    }
    return result;
}

void JavaVM_Free(Jvm* &ptr)
{
    if (ptr && ptr->vm)
    {
        ptr->vm->DetachCurrentThread();
        ptr->vm->DestroyJavaVM();
    }

    delete ptr;
    ptr = nullptr;
}

我之所以使用 JNI_GetCreatedJavaVMs 是为了修复 JDK 中的错误,其中指出:

jint DestroyJavaVM(JavaVM *vm);

Unloads a Java VM and reclaims its resources. The support for DestroyJavaVM was not complete in JDK/JRE 1.1. As of JDK/JRE 1.1 Only the main thread may call DestroyJavaVM. Since JDK/JRE 1.2, any thread, whether attached or not, can call this function. If the current thread is attached, the VM waits until the current thread is the only non-daemon user-level Java thread. If the current thread is not attached, the VM attaches the current thread and then waits until the current thread is the only non-daemon user-level thread. The JDK/JRE still does not support VM unloading, however.

因此,我无法 "create, destroy, create, destroy, repeat"。 相反,我必须在应用程序的生命周期内创建并保留实例,并且仅在我的应用程序即将关闭时销毁该实例。

这很糟糕,因为如果我想将两个不同的 jar 加载到 JVM 中,我做不到。他们可能有也可能没有 类 同名。内存使用率飙升。

因此,我试图找到一种方法来完全卸载 JVM(销毁它)或卸载所有已加载的 类(重置它)。

有什么想法或解决方案吗?

执行此操作的最简单方法是启动一个新进程,然后销毁并完成。

另一个解决方案是使用 ClassLoader 来加载您想要稍后卸载的 类。当一个 ClassLoader 被卸载时,它的所有 类 都被释放了。

顺便说一句,您可以同时加载多个类加载器,甚至可以加载同一个 类.

的不同版本

恕我直言,尝试从 JNI 创建和销毁 JVM 是非常棘手的(尽管不像以前那样棘手),我只会在万不得已时才这样做。有很多方法可以实现您想要的,而且要简单得多。