Question: Assuming I have a class that does some heavy processing, operating with several collections. What I want to do is to make sure that such operation can't lead to out-of-memory or even better I want to set a threshold of how much memory it can use.

```
class MyClass()
{
   public void myMethod()
   {
      for(int i=0; i<10000000; i++)
      {
         // Allocate some memory, may be several collections
      }
   }
}

class MyClassTest
{
   @Test
   public void myMethod_makeSureMemoryFootprintIsNotBiggerThanMax()
   {
      new MyClass().myMethod(); 
      // How do I measure amount of memory it may try to allocate?
   }
}

```

What is the right approach to do this? Or this is not possible/not feasible?

Answer: 
I can think of several options:

* Finding out how much memory your method requires via a microbenchmark (i.e. [jmh](http://openjdk.java.net/projects/code-tools/jmh/)).
* Building allocation strategies based on heuristic estimation. There are several open source solutions implementing class size estimation i.e. [ClassSize](http://svn.apache.org/repos/asf/hbase/branches/0.89-fb/src/main/java/org/apache/hadoop/hbase/util/ClassSize.java). A much easier way could be utilizing a cache which frees rarely used objects (i.e. Guava's Cache). As mentioned by @EnnoShioji, Guava's cache has memory-based eviction policies.

You can also write your own benchmark test which counts memory. The idea is to

1. Have a single thread running.
2. Create a new array to store your objects to allocate. So these objects won't be collected during GC run.
3. `System.gc()`, `memoryBefore = runtime.totalMemory() - runtime.freeMemory()`
4. Allocate your objects. Put them into the array.
5. `System.gc()`, `memoryAfter = runtime.totalMemory() - runtime.freeMemory()`

This is a technique I used in my [lightweight micro-benchmark tool](https://github.com/chaschev/experiments-with-microbes/blob/master/src/test/java/com/chaschev/microbe/samples/MemConsumptionTest.java) which is capable of measuring memory allocation with byte-precision.
The easiest way to estimate memory usage is to use methods from `Runtime` class.
--------------------------------------------------------------------------------

**I suggest not to rely on it, but use it only for approximate estimations. Ideally you should only log this information and analyze it on your own, without using it for automation of your test or code.**

Probably it isn't very reliable, but in closed environment like unit test it may give you estimate close to reality.  

Especially there is no guarantee that after calling `System.gc()` garbage collector will run when we expect it (it is only a suggestion for GC), there are precision limitations of the `freeMemory` method described there: <https://stackoverflow.com/a/17376879/1673775> and there might be more caveats.

### Solution:

```
private static final long BYTE_TO_MB_CONVERSION_VALUE = 1024 * 1024;

@Test
public void memoryUsageTest() {
  long memoryUsageBeforeLoadingData = getCurrentlyUsedMemory();
  log.debug("Used memory before loading some data: " + memoryUsageBeforeLoadingData + " MB");
  List<SomeObject> somethingBigLoadedFromDatabase = loadSomethingBigFromDatabase();
  long memoryUsageAfterLoadingData = getCurrentlyUsedMemory();
  log.debug("Used memory after loading some data: " + memoryUsageAfterLoadingData + " MB");
  log.debug("Difference: " + (memoryUsageAfterLoadingData - memoryUsageBeforeLoadingData) + " MB");
  someOperations(somethingBigLoadedFromDatabase);
}

private long getCurrentlyUsedMemory() {
  System.gc();
  return (Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory()) / BYTE_TO_MB_CONVERSION_VALUE;
}

```