Java单元测试:如何测量方法调用的内存占用量

假设我有一个类,它执行一些繁重的处理,对多个集合进行操作。我想做的是确保这样的操作不会导致内存不足,或者更好的是,我想设置一个可以使用多少内存的阈值。

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?
   }
}

正确的方法是什么?或者这是不可能的/不可行的?


答案 1

我可以想到几个选项:

  • 通过微基准标记(即jmh)找出您的方法需要多少内存。
  • 基于启发式估计构建分配策略。有几个开源解决方案实现了类大小估计,即ClassSize。一种更简单的方法是利用缓存来释放很少使用的对象(即Guava的缓存)。正如@EnnoShioji提到的,番石榴的缓存具有基于内存的驱逐策略。

您还可以编写自己的基准测试来计算内存。这个想法是

  1. 运行单个线程。
  2. 创建一个新数组来存储要分配的对象。因此,在 GC 运行期间不会收集这些对象。
  3. System.gc(),memoryBefore = runtime.totalMemory() - runtime.freeMemory()
  4. 分配对象。将它们放入数组中。
  5. System.gc(),memoryAfter = runtime.totalMemory() - runtime.freeMemory()

这是我在我的轻量级微基准测试工具中使用的一种技术,该工具能够以字节精度测量内存分配。


答案 2

您可以使用探查器(例如 JProfiler)按类查看内存使用情况。或者,如何提到Areo,只是打印内存使用情况:

    Runtime runtime = Runtime.getRuntime();
    long usedMemoryBefore = runtime.totalMemory() - runtime.freeMemory();
    System.out.println("Used Memory before" + usedMemoryBefore);
        // working code here
    long usedMemoryAfter = runtime.totalMemory() - runtime.freeMemory();
    System.out.println("Memory increased:" + (usedMemoryAfter-usedMemoryBefore));

推荐