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

Ser*_*rov 31 java junit testng unit-testing out-of-memory

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

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?
   }
}
Run Code Online (Sandbox Code Playgroud)

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

And*_*hev 16

我可以想到几个选择:

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

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

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

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


pas*_*701 14

您可以使用分析器(例如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));
Run Code Online (Sandbox Code Playgroud)

  • 给更多读者的小提示:值以字节为单位给出,除以 1000000 即可得到以 MB 为单位的值。 (3认同)
  • @Marc_Alx:正好是 1024*1024 == 1048576 (2认同)

Are*_*reo 5

要测量当前内存使用情况,请使用:

Runtime.getRuntime().freeMemory() , Runtime.getRuntime().totalMemory()

这是一个很好的例子: 获取操作系统级别的系统信息

但是这种测量并不精确,但它可以为您提供很多信息。另一个问题GC是不可预测的。