我有一个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 :(得分:2)
处理这种情况的标准方法是构建一个缓存,使用SoftReference
将未使用的对象保留在缓存中,直到GC决定它必须释放该内存。
可以通过-XX:SoftRefLRUPolicyMSPerMB
选项调整(稍微笨拙)确切的行为,但基本原则是可用的内存越多,保留的软引用对象就越长。 (与弱引用不同,which are cleared out at the first opportunity。)
(请注意,SoftReference
存在一些限制其作为常规缓存解决方案的用途的问题:例如,它们在整个VM中共享,或者至少需要< strong>两个 GC循环清除。但它们非常适合在独立应用程序中缓存一些大型对象。)
例如,Guava的CacheBuilder
提供了创建这种缓存的方法。