1

I have a method that create some heavy objects as cache. This objects are rarely accessed, but expensive and slow to process, and are initialized only on demand. Then on use my application, for instance, I could request about three heavy object like that, and reuse them, but too is possible that I run it once and it only occupy memory while I never use it anymore during a session.

My question is: is possible I define that an object is "garbage collectable", then in case of application requires more memory it unset this unused data?

I think that it should works something like that (pseudo-code):

private static MyInstance instance = null;

public static getInstance() {
    if (instance == null) {
        instance = calculate();
        GC.put(instance);
    }

    return instance;
}

I think that I can do it with some kind of Timer, then check from time to time, but I guess that Java should have something like that, to call only if memory is heavy used.

MyStackRunnethOver
  • 4,872
  • 2
  • 28
  • 42
David Rodrigues
  • 12,041
  • 16
  • 62
  • 90

3 Answers3

1

Java does not have a way to manually de-allocate memory (see Memory Management in Java. However, it does have automatic garbage collection. This means that any object that has no references left in the program will be automatically removed. In your case, for example, if an Instance is no longer used (the function that used it returns, and no other references exist, or you overwrite the sole variable that stored a reference to the Instance with something else), that Instance will be garbage-collected.

There is not, however, any method of making the Instance disappear any faster than getting rid of references to it, and letting the garbage collector deal with it.

What I would suggest instead, for your application, is something like an LRU cache (see How would you implement an LRU cache in Java?), which would restrict your memory usage to a set number of instances, which (depending on what exactly Instance is) would limit you to a set amount of memory used by Instances.

If you wanted instead to allow any amount of memory to be used, but not used for very long, you could create a wrapper class for Instance, which implements your cache idea (only creates an Instance when called, if its current copy is null), but keeps a timer and sets its Instance to null after a given amount of time has expired without it being used.

Community
  • 1
  • 1
MyStackRunnethOver
  • 4,872
  • 2
  • 28
  • 42
  • Someone with more knowledge than I have about Java garbage-collection could add information as to whether, when a program is close to running out of memory, the garbage collector tries right then to find things to get rid of. Seems like the speed (relative to memory being used up) with which the garbage collector can be relied on to free up space is important in this context. – MyStackRunnethOver Apr 21 '17 at 04:50
1

What you need is a proper cache implementation. There are tons of them in Java, e.g., Guava Cache, which is highly configurable.

Your calculate method is just CacheLoader#load.

You don't need to care about the GC. Just size your cache properly so that not too much memory gets used. Evicted cache entries get collected automaticaly (when not referenced elsewhere).

I think that I can do it with some kind of Timer, then check from time to time, but I guess that Java should have something like that, to call only if memory is heavy used.

You can use time based eviction with e.g. CacheBuilder#expireAfterWrite. There's no caching in Java itself, but there's SoftReference. Anyway, I don't recommend using it directly, but consider using it with CacheBuilder#softKeys.

maaartinus
  • 44,714
  • 32
  • 161
  • 320
1

Yes, Java offers three types of indirect references which are sensitive to memory usage.

A cache can use a SoftReference that will be cleared before the process raises an OutOfMemoryError. As long as there is plenty of memory, however, the SoftReference will prevent its referent from being garbage collected.

erickson
  • 265,237
  • 58
  • 395
  • 493