简体   繁体   English

从JVM清除所有已加载的类

[英]Clearing all loaded classes from the JVM

I created a JVM via JNI like below: 我通过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;
}

The reason why I use JNI_GetCreatedJavaVMs is to fix the bug in the JDK where it states: 我使用JNI_GetCreatedJavaVMs的原因是为了修复JDK中指出以下错误:

jint DestroyJavaVM(JavaVM *vm); jint DestroyJavaVM(JavaVM * vm);

Unloads a Java VM and reclaims its resources. 卸载Java VM并回收其资源。 The support for DestroyJavaVM was not complete in JDK/JRE 1.1. 在JDK / JRE 1.1中,对DestroyJavaVM的支持不完整。 As of JDK/JRE 1.1 Only the main thread may call DestroyJavaVM. 从JDK / JRE 1.1开始,只有主线程可以调用DestroyJavaVM。 Since JDK/JRE 1.2, any thread, whether attached or not, can call this function. 从JDK / JRE 1.2开始,任何线程(无论是否连接)都可以调用此函数。 If the current thread is attached, the VM waits until the current thread is the only non-daemon user-level Java thread. 如果连接了当前线程,则VM会等待直到当前线程是唯一的非守护程序用户级Java线程。 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. 如果未附加当前线程,则VM会附加当前线程,然后等待直到当前线程是唯一的非守护程序用户级线程。 The JDK/JRE still does not support VM unloading, however . 但是,JDK / JRE仍然不支持VM卸载

Because of this, I'm not able to "create, destroy, create, destroy, repeat". 因此,我无法“创建,销毁,创建,销毁,重复”。 Instead, I have to create, keep instance around for the app's lifetime and only destroy that one instance when my application is about to close. 取而代之的是,我必须创建,在应用程序的生命周期内保留实例,并仅在应用程序即将关闭时销毁该实例。

This sucks because if I want to load two different jars into the JVM, I can't. 这很烂,因为如果我要将两个不同的jar加载到JVM中,就不能这样做。 They may or may not have classes that are the same name. 它们可能具有或不具有相同名称的类。 Memory usage sky-rockets. 内存使用率飞速增长。

Thus, I'm trying to find a way to either unload the JVM completely (destroy it) or unload all classes that was loaded (reset it). 因此,我试图找到一种方法来完全卸载JVM(销毁它)或卸载所有已加载的类(将其重置)。

Any ideas or solutions? 有什么想法或解决方案吗?

The simplest way to do this is to start a new process which you destroy which finished. 最简单的方法是启动一个新进程,然后销毁已完成的进程。

Another solution is to use a ClassLoader to load the classes you want to later unload. 另一个解决方案是使用ClassLoader加载要稍后卸载的类。 When a ClassLoader is unloaded, all it's classes are freed up. 卸载ClassLoader时,将释放其所有类。

BTW You can have multiple ClassLoaders loaded at once, even loading different version of the same classes. 顺便说一句,您可以一次加载多个ClassLoader,甚至可以加载同一类的不同版本。

IMHO Trying to create and destroy JVMs from JNI is very tricky to get right (though not as tricky as it used to be) and I would only do this as a last resort. 恕我直言,尝试从JNI创建和销毁JVM非常棘手(尽管不像以前那样棘手),我只能做为最后的选择。 There many be any number of way to achieve what you want which is much simpler. 有许多方法可以实现所需的目标,这要简单得多。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM