从 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 是非常棘手的(尽管不像以前那样棘手),我只会在万不得已时才这样做。有很多方法可以实现您想要的,而且要简单得多。
我通过 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 是非常棘手的(尽管不像以前那样棘手),我只会在万不得已时才这样做。有很多方法可以实现您想要的,而且要简单得多。