2016-11-02 5 views
3

У меня есть приложение JavaFX, которое отображает TabPane с несколькими вкладками, как обычный браузер.Бесплатный сборщик памяти и мусора

Обычно я загружаю некоторые сетки внутри этих вкладок. Каждый раз, когда выбрана вкладка, старая вкладка содержит, а новая вкладка загружается (с сервера).

Проблема заключается в том, когда вы нажимаете на старую вкладку, вам нужно подождать, прежде чем она будет загружена снова. Я хочу иметь то же поведение, что и современный браузер, и сохранять содержимое в своем приложении. Проблема в том, что я не знаю, сколько памяти было отдано моему приложению, и сколько вкладок можно открыть.

В основном, что я делаю, это проверка того, сколько памяти у меня осталось (следуя этому ответу Java get available memory), и если коротко, я просто освобожу все содержимое вкладки. Поэтому мое приложение может работать с 800Mo памяти, но если у кого-то есть 6Go памяти, опыт будет лучше.

В конце процесса освобождения памяти я вручную вызываю сборщик мусора, потому что я видел, что освобождение содержимого моей вкладки (позволяющее собирать мусор) не является немедленным. Я знаю, что это плохо, но с другой стороны, я не полагаться на сборщик мусора. Если это не вызвано, это не проблема, содержимое моей вкладки будет собрано в какой-то момент. Вот так называемый метод:

/** 
* Before an action that may take some memory, we check how much memory we 
* have left. If memory is short, we go through the Tab in order to release 
* them if possible. 
*/ 
public void verifyMemory() { 
    long allocatedMemory = (Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory()); 
    long memoryLeft = Runtime.getRuntime().maxMemory() - allocatedMemory; 
    System.out.println(memoryLeft/1000000); 
    //We must release some memory 
    if (memoryLeft < MEMORY_TRESHOLD) { 
     LOGGER.warn("Memory treshold is hit, we must release memory"); 
     for (Tab tab : getTabs()) { 
      if (tab instanceof MyTab) { 
       ((MyTab) tab).destroyIfPossible(); 
      } 
     } 
     System.gc(); 
    } 
} 

Есть ли у вас сильный совет против моего решения? Или любые идеи, которые могли бы улучшить или помочь мне достичь моей цели?

+0

Да, нет гарантии, что это вызвано при вызове ... System.gc(); –

+1

Да, это не гарантировано. Хотя, это будет работать в большинстве случаев. –

+0

Вещь, я не полагаюсь на нее. Если это называется, это лучше, если нет, это тоже не проблема. Вот почему я позволил себе называть это. – Maxoudela

ответ

2

Стандартный способ справиться с этим сценарием заключается в создании кеша, который использует SoftReference s для хранения неиспользуемых объектов в кэше до тех пор, пока GC не решит, что это абсолютно необходимо для освобождения этой памяти.

Точное поведение можно настроить (слегка неловко) с помощью опции -XX:SoftRefLRUPolicyMSPerMB, но основным принципом является то, что чем больше свободной памяти доступно, тем более длинные объекты с мягкой привязкой сохраняются. (В отличие от слабых ссылок, which are cleared out at the first opportunity.)

(Пожалуйста, обратите внимание, что есть несколько проблем с SoftReference, которые ограничивают их полезность в качестве общего решения кэша: например, тот факт, что они являются общими для всей виртуальной машины, или что они требуют по крайней мере, два циклов GC, чтобы очистить. Но они идеально подходят для кэширования несколько массивных объектов в виде отдельного приложения.)

гуавы-х CacheBuilder, например, предлагает создать вам только что-то кэш.

+0

Проблема в том, что мне не нужно только содержимое моей вкладки. У меня есть экосистема вокруг моей вкладки, и я хочу уничтожить все это или ничего. Возможно, я мог бы все это сделать в SoftReference. Также мне нужно провести какое-то живое тестирование, чтобы увидеть, когда эти softReference сбрасываются. Вы говорите «абсолютно необходимо освободить», но в документации говорится, что это «по усмотрению» сборщика мусора. – Maxoudela

+0

@Maxoudela Вы правы, единственная твердая гарантия заключается в том, что GC очистит все мягкие ссылки, прежде чем сдаться и выбросить «OutOfMemoryException». Но во всех реализациях JVM, которые я знаю, мягкие ссылки имеют достаточно продолжительный жизненный опыт, если у вас не осталось свободной памяти. И наоборот, это стандартный способ взаимодействия с сборщиком мусора. – biziclop

+0

[Здесь] (http://jeremymanson.blogspot.com/2009/07/how-hotspot-decides-to-clear_07.html) сообщение, объясняющее, как это работает в Oracle/OpenJDK. Он довольно старый, поэтому некоторые детали могут измениться, но не сильно. – biziclop