3

I have a JavaFX application that display a TabPane with multiple Tabs, like a normal browser.

I usually load some grids inside these Tabs. Every time a tab is selected, the old tab content is trashed and the new tab is loaded (from a server).

The problem is when you click on the old tab, you have to wait before it's loaded again. I want to have the same behavior as modern browser, and save the content in my application. The problem is, I don't know how much memory is given to my application, and how much tab can be opened.

Basically, what I'm doing is checking how much memory I have left (by following this answer Java get available memory ), and if I'm short, I just release all the tab content. Therefore, my application is able to run with 800Mo of memory, but if someone have 6Go of memory, the experience will be better.

At the end of the memory release process, I manually call the garbage collector because I've seen that releasing my tab content (allowing them to be garbage collected) is not immediate. I know it's bad, but on another hand, I don't rely on the garbage collector. If it's not called, it's not a problem, my tab's content will be collected at some point. Here is the so called method :

/**
 * 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();
    }
}

Do you have strong advice against my solution? Or any ideas that could improve or help me achieving my goal?

Maxoudela
  • 2,091
  • 3
  • 15
  • 23

1 Answers1

2

The standard way to deal with this scenario is to build a cache that uses SoftReferences to keep unused objects in the cache until the GC decides it absolutely has to free up that memory.

The exact behaviour can be tuned (slightly awkwardly) via the -XX:SoftRefLRUPolicyMSPerMB option, but the basic principle is that the more free memory is available, the longer softly referenced objects are preserved. (Unlike weak references, which are cleared out at the first opportunity.)

(Please note that there are several issues with SoftReference that limit their usefulness as a general cache solution: for example the fact that they are shared across the entire VM, or that they require at least two GC cycles to clear. But they are ideal for caching a few massive objects in a standalone application.)

Guava's CacheBuilder for example offers to create you just that sort of cache.

Community
  • 1
  • 1
biziclop
  • 48,926
  • 12
  • 77
  • 104
  • Problem is that it's not just my tab content that I need to trash. I kinda have an ecosystem around my Tab, and I want to trash all of that or nothing.. Maybe I could wrap all that into a SoftReference indeed.. Also, I need to do some live testing in order to see when these softReference are trashed. You say "absolutely has to free" but the documentation says it's "at the discretion" of the garbage collector.. – Maxoudela Nov 02 '16 at 14:11
  • @Maxoudela You're right, the only hard guarantee is that the GC will clear all soft references before giving up and throwing an `OutOfMemoryException`. But in all the JVM implementations I know, soft references have a long enough life in practice, unless you run out of free memory. And the upside is that it's a standard way of interacting with the garbage collector. – biziclop Nov 02 '16 at 14:17
  • [Here's](http://jeremymanson.blogspot.com/2009/07/how-hotspot-decides-to-clear_07.html) a post explaining how it works in Oracle/OpenJDK. It's fairly old, so some of the details might have changed, but not drastically. – biziclop Nov 02 '16 at 14:21