我有一些使用以下配方的数据处理代码:
当有尽可能少的块时,最后一个阶段是最有效的,所以我希望第一阶段读入适合内存的数据。我可以通过查询Runtime.freeMemory()
来完成此任务。
但是,这意味着我需要调用System.gc()
,或者Runtime.freeMemory()
返回的数字远小于我可以安全分配的内存量。
我听到很多当局说明确调用System.gc()
是一个坏主意。有什么办法可以避免这种情况吗?
答案 0 :(得分:2)
即使你在检查你有多少内存之前调用System.gc(),也不能保证实际上会发生垃圾收集。我自己真的不会打扰,我会设置一个固定的块大小(最好通过属性或类似配置)并始终使用它。如果你的程序的其余部分足够简单,你可以使用块大小加上固定数量的megs作为堆大小。如果程序的大小由于其他原因而太不确定,您可以考虑并排运行两个程序并使用IPC机制。
当然很可能你的代码需要对内存进行更精细的控制,但我谦虚地建议你使用错误的语言;或者至少是错误的运行时(那里有RT java产品,我认为他们更倾向于这种事情。)
我很抱歉,如果这看起来不是最有用的答案,但基本上我想知道你是否真的需要这个?
答案 1 :(得分:1)
调用System.gc()是一个坏主意的原因很可能是因为它不保证任何内容。
调用System.gc()是一个坏主意的真正的原因是JVM最了解运行GC的最佳时间;即当堆满了。如果您在其他时间调用System.gc(),则告诉JVM执行昂贵且浪费的操作。
回到最初的问题,我认为最好的解决方案是不要尝试编写应用程序来猜测内存分配器。相反,对应用程序进行编码,使得块大小是命令行参数/系统属性/等等,并手动调整块大小与JVM内存大小。您可能还希望确保JVM初始和最大内存大小相同。
答案 2 :(得分:0)
缓存freememory的第一个值,重用它并让VM完成工作。
答案 3 :(得分:0)
非常好的时机。我今天早些时候问了this并得到了一些有用的答案,希望它有所帮助。
编辑:这并不能真正回答你的问题,但它指的是调用System.gc()不是一个好主意。
答案 4 :(得分:0)
使用JConsole或类似的东西
答案 5 :(得分:0)
调用System.gc()是一个坏主意的原因很可能是因为它不保证任何东西。
如果你真的想确定JVM进行垃圾收集,你必须告诉它。一种方法与JConsole相同,即通过JMX。
请参阅http://java.sun.com/j2se/1.5.0/docs/guide/management/agent.html#local
答案 6 :(得分:0)
使用JMX怎么样?特别是MemoryMXbean:
MemoryMXBean memoryMXBean = ManagementFactory.getMemoryMXBean();
另请查看MemoryUsage class。
答案 7 :(得分:-1)
JVM Tool INterface(jvmti)有一个名为ForceGarbageCollection的方法。你可以写一些JNI来调用它。
类似
#include "jvmti.h"
#include "jni.h"
jvmtiEnv *jvmti;
JNIEXPORT jint JNICALL
Agent_OnLoad(JavaVM *vm, char *options, void *reserved) {
(*vm)->GetEnv(vm, (void **)&jvmti, JVMTI_VERSION_1);
return JNI_OK;
}
JNIEXPORT void JNICALL my_managled_function_name_that_is_entirely_too_long_to_be_easy_to_use (JNIEnv *env) {
error = (*jvmti)->ForceGarbageCollection(jvmti);
// you can trap the error if you want;
}
顺便说一下,这是一个坏主意。我只使用此代码进行调试(以确保某些类(如侦听器)没有更多可访问的引用。)
我敢打赌,VM会在抛出内存错误之前gc所有可能的数据。