2009-07-18 27 views
2

我有使用以下配方的一些数据处理代码:如何估计调用System.gc()时剩余的内存量?

  • 读入尽可能多的数据将装入内存(这可称为“块”)
  • 在块
  • 写进行处理出处理块磁盘
  • 重复
  • ...
  • 合并所有的处理块,以获得最终的答案。

最后一个阶段在块数尽可能少的情况下效率最高,所以我希望第一阶段能够读入尽可能多的数据以适应内存。我可以通过查询Runtime.freeMemory()来做到这一点。

但是,这意味着我需要拨打System.gc(),或Runtime.freeMemory()返回的号码比我可以安全分配的内存量要小得多。

我听说过一些权威人士说,明确呼吁System.gc()是一个坏主意。有什么办法可以避免这种情况吗?

回答

0

缓存freememory的第一个值,重用它并让VM执行此操作。

+0

当然,如果我有一个可靠的方法来测量我分配的内存量时,这只会有所帮助。 – 2009-07-18 14:32:06

+0

即使这样也不行,因为虚拟机可能已经生成了随后由其他进程分配的页面。但在这种情况下的经验法则是,第一个大约至少是可预测的。 – 2009-07-18 16:38:20

0

非常好的时机。我今天早些时候问过this,并得到了一些有用的答案,希望它有帮助。

编辑:这并没有真正回答你的问题,但它指的是调用System.gc()不是一个好主意。

0

使用JConsole的或类似的东西

2

即使你调用System.gc()右检查您有多少内存之前,还不能保证垃圾收集实际上会发生。我自己,我真的不会打扰,我会设置一个固定的块大小(最好通过属性或类似的配置),并始终使用它。如果程序的其余部分足够简单,那么可以使用块大小加上固定数量的megs作为堆大小。如果程序的大小由于其他原因而过于不确定,则可以考虑并行运行两个程序并使用IPC机制。

当然,很可能你的代码需要对内存进行更细致的控制,但我会虚心地建议你使用错误的语言;或者至少是错误的运行时(这里有RT的Java产品,我认为它们更适合这种事情)。

对不起,如果这看起来不是最有用的答案,但基本上我想知道你是否真的需要这个?

1

理由调用System.gc()是一个坏主意是最有可能的,因为它并不能保证什么。

real调用System.gc()是一个坏主意的原因是JVM最好知道运行GC的最佳时间;即当堆满时。如果您在其他时间调用System.gc(),则会告诉JVM执行昂贵而浪费的操作。

回到最初的问题,我认为最好的解决方案是不要试图编写应用程序来猜测内存分配器。相反,对应用程序进行编码以使块大小为命令行参数/系统属性/无论如何,并手动调整块大小与JVM内存大小。您可能还需要确保JVM的初始和最大内存大小相同。

-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所有可能的数据。

相关问题