在JConsole下观察到的以下代码显示了堆大小的不断增加。堆最多可达25mb,然后GC运行并将堆大小减少到接近3MB。这是预期的行为吗?我很惊讶!
public class Dummy {
public static void main(String[] args) {
System.out.println("start");
while(true){
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
我正在使用Snow Leopard。
答案 0 :(得分:8)
与jconsole通信会导致分配对象。我相信你在这里看到的是你的测量方法的神器。在编译代码时,HotSpot可能还会进行轻微分配。如果您担心,请使用分析器查看正在分配的内容(同样,请注意分析器界面的分配)。
正常的GC行为是为了避免不必要的运行。您将在整个网络上看到内存使用情况的锯齿图。缓存和交换友好性与避免工作之间存在一些妥协。此外,服务器HotSpot比客户端HotSpot更积极地使用内存。
答案 1 :(得分:4)
是的,这应该是预期的行为。虽然你没有做任何特定于分配对象的事情,但是睡眠的实现可能是,即使没有,也可以在JVM中运行其他线程,这很可能是。
答案 2 :(得分:3)
是的,这很正常。您没有显式创建任何对象,但是您正在调用可能会创建一些临时对象的方法作为其实现的一部分。那些临时对象堆积起来,直到GC运行清除它们为止。
答案 3 :(得分:2)
类文件看起来像这样,代码循环从8到14,java.lang.Thread.sleep()是本机的。因此没有理由创建MB的对象
public static void main(java.lang.String[] args);
0 getstatic java.lang.System.out : java.io.PrintStream [16]
3 ldc <String "start"> [22]
5 invokevirtual java.io.PrintStream.println(java.lang.String) : void [24]
8 ldc2_w <Long 5000> [30]
11 invokestatic java.lang.Thread.sleep(long) : void [32]
14 goto 8
17 astore_1 [e]
18 aload_1 [e]
19 invokevirtual java.lang.InterruptedException.printStackTrace() : void [38]
22 goto 8
我担心你看到的是来自JProfiler本身(我不知道你是如何将它附加到你的Dummy测试应用程序)或其他在这个vm中运行的东西。要找出已创建的对象,如果JProfiler不显示此信息,则应执行堆转储。
答案 4 :(得分:1)
关于原因,显然有两种理论,并且不可能基于经验推理来区分它们。我可以建议一个简单的实验。
将程序更改为休眠1毫秒而不是5000.(实际数字无关紧要......这是为了使假设的内存分配尽可能快地发生。你也可以尝试0毫秒,但睡眠的行为可能会有所不同......)
使用当前方法运行程序;例如与jconsole。
运行没有jconsole等的程序,但使用“-verbose:gc”选项,以便您可以看到GC运行的时间。
我怀疑你会在最后一个案例中等待GC运行时耐心等待......甚至尽可能快地调用sleep
。