我正在尝试在不同使用级别的Tomcat Java EE应用程序中测量自己的数据结构的内存使用情况。
测量内存使用情况我尝试了两种策略:
运行时freeMemory和totalMemory:
System.gc(); //about 20 times
long start = Runtime.getRuntime().freeMemory();
useMyDataStructure();
long end = Runtime.getRuntime().freeMemory();
System.out.println(start - end);
MemoryPoolMXBean.getPeakUsage():
long before = Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory();
List<MemoryPoolMXBean> memorymxbeans = ManagementFactory.getMemoryPoolMXBeans();
for(MemoryPoolMXBean memorybean: memorymxbeans){
memorybean.resetPeakUsage();
}
useMyDataStructure();
for(MemoryPoolMXBean memorybean: memorymxbeans){
MemoryUsage peak = memorybean.getPeakUsage();
System.out.println(memorybean.getName() + ": " + (peak.getUsed() - before));
}
方法1根本不会输出可靠数据。这些数据毫无用处。
方法2输出负值。除此之外,getName()
告诉我它分别输出Code Cache
,PS Eden Space
,PS Survivor Space
和PS Old Gen
。
如何在Java useMyDataStructure()
调用之前和之后获取一些一致的内存使用数?我不想使用VirtualVM,我更喜欢在long
对象中捕获数字并将其写入文件。
提前致谢。
编辑1:
上述示例中的 useMyDatastructure
试图简化代码。那是什么:
int key = generateKey();
MyOwnObject obj = makeAnObject();
MyContainerClass.getSingleton().addToHashMap(key, obj);
所以从本质上讲,我真的想测量HashMap<Integer, MyOwnObject>
中MyContainerClass
占用的内存量。我将使用此内存测量来执行实验,其中我将填充HashMap和MyOwnObject实例。
答案 0 :(得分:1)
java中所有大小调整对象中的第一个都是非常重要的(正如非常好地解释here)。
如果您想知道特定对象的大小,至少有2个开源库可供您进行数学计算 - java.sizeof和javabi-sizeof
现在,至于你的具体测试 - 无论你调用多少次,现代(热点)jvms都会忽略System.gc()。另外,您的useMyDataStructure()
方法是否可能不保留对其创建的对象的引用?在这种情况下,在调用它之后测量空闲内存是不好的,因为任何已分配的对象可能已被清除。
答案 1 :(得分:1)
你可以尝试https://github.com/jbellis/jamm,这对我很有帮助。