2009-07-18 2 views
2

У меня есть некоторый код обработки данных, который использует следующий рецепт:Как оценить объем памяти, оставшийся при вызове System.gc()?

  • чтения в столько данных, сколько поместится в памяти (называют это «кусок»)
  • выполнять обработку на куске
  • Написать из обрабатываются кусок на диск
  • Repeat
  • ...
  • Объединить все обработанные куски, чтобы получить окончательный ответ.

Этот последний этап наиболее эффективен, когда есть как можно меньше кусков, поэтому я хочу, чтобы первый этап считывал столько данных, сколько поместилось в память. Я могу сделать это, запросив Runtime.freeMemory().

Однако это означает, что мне нужно позвонить System.gc(), или номер, возвращаемый Runtime.freeMemory(), намного меньше объема памяти, которую я мог бы безопасно распределить.

Я слышал, что ряд органов власти заявили, что вызов System.gc() явно является плохими идеями. Есть ли способ избежать этого?

ответ

0

Прикрепите первое значение freememory, используйте его повторно и дайте VM работать.

+0

Несомненно, это поможет, если у меня есть надежный способ измерения объема памяти, которую я выделяю, когда я иду. –

+0

Даже тогда это не сработает, поскольку VM, возможно, уступила страницы, которые впоследствии выделяются другими процессами. Но эмпирическое правило в таких случаях заключается в том, что первое приближение, по крайней мере, предсказуемо. –

0

Очень хорошее время. Вчера я спросил this и получил полезные ответы, надеюсь, что это поможет.

EDIT: это не отвечает на ваш вопрос, но это относится к вызову System.gc(), не являющемуся хорошей идеей.

0

использование JConsole или что-то подобное

+0

Используйте JConsole, чтобы сделать что, извините? Мне нужно сделать это программно. –

+0

поэтому изучите источники JConsole ... – dfa

2

Даже если вы звоните System.gc() прямо перед проверкой, сколько памяти у вас есть, нет никакой гарантии, что вывоз мусора будет на самом деле произошло. Сам я действительно не стал бы беспокоиться, я бы установил фиксированный размер куска (предпочтительно настроенный через свойство или подобное) и всегда использую это. Если остальная часть вашей программы достаточно проста, вы можете просто использовать размер куска плюс фиксированное количество мегабайтов в качестве размера кучи. Если размер вашей программы слишком неопределен из-за других причин, вы можете изучить две программы бок о бок и использовать механизм IPC.

Конечно, вполне возможно, что ваш код нуждается в более тонком контроле над памятью, но я смиренно предлагаю вам использовать неправильный язык; или, по крайней мере, неправильное время выполнения (есть предложения RT java, я предполагаю, что они больше ориентированы на подобные вещи).

Прошу прощения, если это не похоже на самый полезный ответ, но в основном мне интересно, действительно ли вам это нужно?

0

Причина, по которой вызвать System.gc() - плохая идея, скорее всего, потому что она ничего не гарантирует.

Если вы действительно хотите быть уверенным, что JVM делает сборку мусора, вы должны сказать это. Один из способов аналогичен JConsole, а именно через JMX.

См http://java.sun.com/j2se/1.5.0/docs/guide/management/agent.html#local

1

Причиной, побуждающей вызова System.gc() является плохой идеей, скорее всего, потому что это ничего не гарантирует.

реальная причина, что вызов System.gc() это плохая идея состоит в том, что виртуальная машина лучше в зная оптимальное время для запуска 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; 
} 

Кстати, это плохая идея. Я использую этот код только для отладки (чтобы убедиться, что у определенного класса, такого как слушатели, нет более доступных ссылок.)

Моя ставка заключается в том, что виртуальная машина будет собирать все возможные данные, прежде чем бросать ошибки памяти.

0

что касается использования JMX? В частности MemoryMXbean:

MemoryMXBean memoryMXBean = ManagementFactory.getMemoryMXBean(); 

проверьте также MemoryUsage class.