1

I have a java application that uses extensively the memory. It keeps a data-structure that grows very fast and is the responsible for the biggest amount of memory used.

In order to avoid an Out Of Memory, I decide to flush the data-structure to a repository (file or db) and post process it.

The problem that I face consists of choosing the time(when the used memory is "close" to reach the maximum allowed) to flush the data-structure into the repository. One way would be to keep track of the data-structure's memory usage on every update.

         dataStructure.onUpdate(new CheckMemoryIfReachedMax() {
               public void onUpdate(long usedMemory) {
                    if (usedMemory == MaxMemory) {
                        datastucture.flushInRepository();
                    }
               } 
         }

The main problem in this case is that isnt easy to change the data-structure to keep track of the memory.

Another possible solution would be to get the used memory from the JVM and compare it to the maximum memory.

          Runtime runtime = Runtime.getRuntime();
          long freeMemory = runtime.freeMemory();
          if (freeMemory < MaxUsedMemory) {
              datastucture.flushInRepository();
          }

In this case the problem is that the memory usage just gives a hint of how much memory is used, being that we cannot predict the moment the Garbage Collector removes the objects. This solution would make me flush more often the data-structure to the repository, so the application performance might suffer from this.

Is there any general pattern used in those cases? Do you have any suggestion about which of the solution would be better suited to the problem?

pokeRex110
  • 833
  • 2
  • 14
  • 26
  • Maybe expand the second solution to first trigger GC (`runtime.gc()`) and only flush if that doesn't free up considerable amount of memory? –  Aug 27 '15 at 09:25
  • @doublep - I don't think calling GC explicitly (that too in what looks like production code) is a good idea. – TheLostMind Aug 27 '15 at 09:26
  • Check out [Monitoring own memory usage by Java application](http://stackoverflow.com/questions/10754748/monitoring-own-memory-usage-by-java-application) – Jordi Castilla Aug 27 '15 at 09:31

2 Answers2

1

I think you should use the first approach because comparing runtime memory is dependent on many things. Hence for using first approach and to get usedMemory by an object you can use

long getObjectSize(Object objectToSize)

from Instrumentation Interface to get an approximate size of your object.

Refer http://docs.oracle.com/javase/6/docs/api/java/lang/instrument/Instrumentation.html#getObjectSize(java.lang.Object)

harshitpthk
  • 4,058
  • 2
  • 24
  • 32
1

There is no good, universal definition of "memory used by JVM", the best choice is to track the size of the structure yourself, sorry.

The problem is - JVM uses memory both for garbage and actual data, and there is no way to tell one from the other until actual garbage collection occurs. This is by design and actually is a major optimization.

A dirty workaround would be to use JMX to track the amount of memory freed during the last collection (this will be the size of the short-lived garbage). This has two drawbacks:

  • you will get false positives once the long-lived garbage accumulates;
  • you will depend on a specific garbage collector and garbage collector settings (for example I have no idea if this scheme is achievable with G1).
fdreger
  • 12,264
  • 1
  • 36
  • 42