Java 特定对象列表的内存使用情况

Java 特定对象列表的内存使用情况,java,unit-testing,memory-management,Java,Unit Testing,Memory Management,我有一个simplespojo(一个用户类)列表,其中包含大约15个简单字段和1个arrayList。 这些代表用户&可能100或1000个用户将存储在内存中,以避免每次从外部系统检索它们。(我正在使用Ehcache) 我想通过junit测试了解K个用户列表使用了多少内存。 我的直觉是,像这样的简单pojo即使是1000个pojo也不会有任何威胁(换句话说,不到100KO) 提前感谢您的回复。 非常感谢您的帮助。您可以将它们写入字节输出流,然后获取字节数组并检查其长度。如果您的POJO是可序列化

我有一个simplespojo(一个用户类)列表,其中包含大约15个简单字段和1个arrayList。 这些代表用户&可能100或1000个用户将存储在内存中,以避免每次从外部系统检索它们。(我正在使用Ehcache)

我想通过junit测试了解K个用户列表使用了多少内存。 我的直觉是,像这样的简单pojo即使是1000个pojo也不会有任何威胁(换句话说,不到100KO)

提前感谢您的回复。
非常感谢您的帮助。

您可以将它们写入
字节输出流
,然后获取字节数组并检查其长度。如果您的POJO是可序列化的,这将起作用

您可以在创建对象之前和之后计算JRE使用的内存,以便估算对象正在使用的字节数

System.gc();
System.runFinalization();
Thread.sleep(1000);
long before = Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory();

//build object here

System.gc();
System.runFinalization();
Thread.sleep(1000);
long after = Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory();

long objectSize = after - before;

如果需要一个简单的测试,可以将新大小设置为大,然后执行以下操作。 仅当新大小远远大于正在创建的数据时,此选项才有效。 e、 g

-XX:NewSize=1g-verbosegc

如果您没有看到任何GC,则该值将是正确的

long before = Runtime.getRuntime().freeMemory();

//build object here

long used = before - Runtime.getRuntime().freeMemory();
注意:这假设您不生成临时对象。

有一个实用程序库可以分析对象布局和内存占用

将依赖项添加到项目中(例如使用gradle
编译'org.openjdk.jol:jol-core:0.9'
),然后可以使用助手类打印或检查具体对象的内存占用

//打印虚拟机详细信息
System.out.println(VM.current().details());
//创建新对象(这可以是您自己的数据类)
Map o=新的HashMap();
o、 放置(“键1”,123L);
//检查对象大小(例如:从单元测试)
System.out.println(“浅尺寸:+VM.current().sizeOf(o));
System.out.println(“总大小:+GraphLayout.parseInstance(o.totalSize());
System.out.println();
//打印对象详细信息的步骤
System.out.println(ClassLayout.parseInstance(o.toPrintable());
System.out.println(GraphLayout.parseInstance(o.toPrintable());
System.out.println(GraphLayout.parseInstance(o.toFootprint());
本例在
Java热点(TM)64位服务器虚拟机(构建25.191-b12,混合模式)上的输出
Java版本“1.8.0_191”


为什么要用JUnit测试来实现这一点?这些值很可能取决于JVM版本/供应商/标志和CPU体系结构。对于iNtance,64位Linux上的Sun JVM!=Sun在32位Linux上的JVM!=Sun的JVM在64位Linux上使用CompressedOops。你最好的是个案分析。我也知道这取决于很多事情,但我希望我自己的架构有一些真正的价值&我们在生产中使用的架构。我假设K个使用N字节的简单用户在其他体系结构上的消耗量可能不会超过100倍。非常感谢,Dogbane,这就是我一直在寻找的解决方案。是的。sleep允许GC完成工作,因为它是异步的。简单而优雅!我发现这个解决方案很好——直到我尝试了它。我认为它给出了完全错误的、不可信的结果(为什么…)。多么可悲,听起来如此美妙:''-(
# Running 64-bit HotSpot VM.
# Using compressed oop with 3-bit shift.
# Using compressed klass with 3-bit shift.
# Objects are 8 bytes aligned.
# Field sizes by type: 4, 1, 1, 2, 2, 4, 4, 8, 8 [bytes]
# Array element sizes: 4, 1, 1, 2, 2, 4, 4, 8, 8 [bytes]

Shallow size: 48
Total size: 232

java.util.HashMap object internals:
 OFFSET  SIZE                       TYPE DESCRIPTION                               VALUE
      0     4                            (object header)                           01 52 99 6a (00000001 01010010 10011001 01101010) (1788432897)
      4     4                            (object header)                           2d 00 00 00 (00101101 00000000 00000000 00000000) (45)
      8     4                            (object header)                           a3 37 00 f8 (10100011 00110111 00000000 11111000) (-134203485)
     12     4              java.util.Set AbstractMap.keySet                        null
     16     4       java.util.Collection AbstractMap.values                        null
     20     4                        int HashMap.size                              1
     24     4                        int HashMap.modCount                          1
     28     4                        int HashMap.threshold                         12
     32     4                      float HashMap.loadFactor                        0.75
     36     4   java.util.HashMap.Node[] HashMap.table                             [(object), null, null, null, null, null, null, null, null, null, null, null, null, null, null, null]
     40     4              java.util.Set HashMap.entrySet                          null
     44     4                            (loss due to the next object alignment)
Instance size: 48 bytes
Space losses: 0 bytes internal + 4 bytes external = 4 bytes total

java.util.HashMap@2d6a9952d object externals:
          ADDRESS       SIZE TYPE                      PATH                           VALUE
        7410cb2b8         24 java.lang.Long            .table[0].value                123
        7410cb2d0    5383088 (something else)          (somewhere else)               (something else)
        7415ed680         48 java.util.HashMap                                        (object)
        7415ed6b0         24 java.lang.String          .table[0].key                  (object)
        7415ed6c8         24 [C                        .table[0].key.value            [k, e, y, 1]
        7415ed6e0         80 [Ljava.util.HashMap$Node; .table                         [(object), null, null, null, null, null, null, null, null, null, null, null, null, null, null, null]
        7415ed730         32 java.util.HashMap$Node    .table[0]                      (object)


java.util.HashMap@2d6a9952d footprint:
     COUNT       AVG       SUM   DESCRIPTION
         1        24        24   [C
         1        80        80   [Ljava.util.HashMap$Node;
         1        24        24   java.lang.Long
         1        24        24   java.lang.String
         1        48        48   java.util.HashMap
         1        32        32   java.util.HashMap$Node
         6                 232   (total)