我使用Runtime.getRuntime().totalMemory()
和freeMemory()
来计算内存。但是,我对结果感到困惑。
我已经阅读过帖子:
What are Runtime.getRuntime().totalMemory() and freeMemory()?
a question on Runtime.getRuntime().totalMemory()
这是我的演示代码:
package test;
class Memory
{
public static long used()
{
long total=Runtime.getRuntime().totalMemory();
long free=Runtime.getRuntime().freeMemory();
return (total-free);
}
}
package test;
import java.util.ArrayList;
public class MemTestQuestion {
private static final long _10M = 10000000;
public static void main(String[] args) {
int runCount=10;
for (int i = 0; i < runCount; i++) {
arrayListMemTest();
}
}
public static void arrayListMemTest()
{
long startTime = System.currentTimeMillis();
long startMem=Memory.used();
ArrayList<Integer>al= new ArrayList<Integer>();
for (int i = 0; i < _10M; i++) {
al.add(1000);
}
long endMem= Memory.used();
long endEndTime = System.currentTimeMillis();
long timeLast = endEndTime - startTime;
long memUsed = endMem-startMem;
System.out.print("lasts:"
+ timeLast + "ms = "+timeLast/1000.0+"s\t");
System.out.println("mem used:"
+memUsed+"bytes = "+new java.text.DecimalFormat("#.00").format(memUsed/(1024*1024.0))+"M");
System.gc();
}
}
以下是runCount = 1(位于Main方法中的变量)的结果:
lasts:3606ms = 3.606s mem used:214644488bytes = 204.70M
以下是runCount = 10时的结果:
lasts:3643ms = 3.643s mem used:214644488bytes = 204.70M
lasts:389ms = 0.389s mem used:254054928bytes = 242.29M
lasts:366ms = 0.366s mem used:219163424bytes = 209.01M
lasts:242ms = 0.242s mem used:256265992bytes = 244.39M
lasts:222ms = 0.222s mem used:255523768bytes = 243.69M
lasts:225ms = 0.225s mem used:253843192bytes = 242.08M
lasts:253ms = 0.253s mem used:253967736bytes = 242.20M
lasts:236ms = 0.236s mem used:253994680bytes = 242.23M
lasts:234ms = 0.234s mem used:254066232bytes = 242.30M
lasts:233ms = 0.233s mem used:254091448bytes = 242.32M
让我最困惑的是,当runCount=10
时,最多的结果是大约240M。但是当runCount=1
时,结果大约是200M。
我想这是因为JAVA JVM没有及时收集垃圾,所以第一个结果更有说服力。 我是对的吗?如果没有,有人可以提供一些线索或其他建议吗?提前致谢。
演示代码的目的是尝试比较标准的java容器和第三方的容器。
答案 0 :(得分:3)
我想这是因为JAVA JVM没有及时收集垃圾,所以第一个结果更有说服力。我对吗?
我不这么认为。运行System.gc()
应该是一个提示“尽最大努力”收集所有垃圾的提示。马上。提示可以忽略,但如果GC确实运行,您可以期望它执行&gt;&gt;完整&lt;&lt;收集,只有在完成后才返回。 GC不应该“跟上”。
如果没有,有人可以提供一些线索或其他建议吗?
这可能是由于JIT编译和其他JVM预热效果。
当您的应用程序启动时,您的代码的方法和所有使用的(传递)库方法都是字节码,并将由字节码解释器解释。在解释字节码时,JVM会收集各种事物的统计信息(例如,协助分支预测)。最终,它决定JIT编译方法。
那么这与你的观察有什么关系?
统计信息存储在堆中,并且可以访问...直到JIT编译器“消耗”它们。
JIT编译器异步运行,当它运行时,它也将使用堆空间来保存其数据结构。
在启动时,JVM必须加载类,这也会占用堆空间来保存临时对象。
堆大小不是常量。它会增长(有时缩小),具体取决于每个GC循环后可用空间的大小。
在JVM预热阶段,所有这些结合起来在堆大小和堆空间使用方面给出了本地“高点”和“低点”。
答案 1 :(得分:2)
我按照以下方式创建set_source_files_properties(${td_file} PROPERTIES GENERATED true)
..
ArrayList
运行代码之后,我意识到你的混乱结果并没有发生,因为 ArrayList<Integer> al = new ArrayList<Integer>(){
@Override
protected void finalize() throws Throwable {
super.finalize();
System.out.println("finalize");
}
};
没有收集垃圾。上述代码的结果如下:
持续时间:4875ms =使用4.875s内存:250675056bytes = 239.06M
持续时间:437ms = 0.437s内存使用:278614888bytes = 265.71M
完成
完成
持续时间:594ms = 0.594s内存使用:252543848bytes = 240.84M
完成
持续时间:266ms = 0.266s内存使用:277680536bytes = 264.82M
完成
持续时间:312ms = 0.312s内存使用:280390568bytes = 267.40M
完成
持续时间:297ms = 0.297s内存使用:278106248bytes = 265.22M
完成
持续时间:297ms = 0.297s内存使用:277852312bytes = 264.98M
完成
持续时间:312ms = 0.312s内存使用:277885640bytes = 265.01M
完成
持续时间:297ms = 0.297s内存使用:277897448bytes = 265.02M
完成
持续时间:312ms = 0.312s内存使用:277899896bytes = 265.03M
敲定
在此代码中,第一次运行时,它显示的值(JVM
)小于平均值。
然后我更改了239.06M
main method
结果是:
持续时间:2640ms = 2.64s使用的mem:275635104bytes = 262.87M
持续时间:624ms = 0.624s内存使用:253167968bytes = 241.44M
完成
完成
持续时间:411ms = 0.411s内存使用:303362328bytes = 289.31M
完成
持续时间:527ms = 0.527s内存使用:253055288bytes = 241.33M
完成
持续时间:329ms = 0.329s内存使用:280855512bytes = 267.84M
完成
持续时间:340ms = 0.34s内存使用:252478904bytes = 240.78M
完成
持续时间:350ms = 0.35s内存使用:277791960bytes = 264.92M
完成
持续时间:312ms = 0.312s内存使用:277059280bytes = 264.22M
完成
持续时间:314ms = 0.314s内存使用:279330968bytes = 266.39M
完成
持续时间:376ms = 0.376s内存使用:278511960bytes = 265.61M
敲定
这一次,它显示了public static void main(String[] args) throws InterruptedException {
Thread.sleep(7000);
int runCount = 10;
for (int i = 0; i < runCount; i++) {
arrayListMemTest();
}
}
附近的平均值。
我认为,260M
需要一些时间来完全加载其库。程序在完全初始化JVM
之前运行。