Java 未请求的内存分配
下面在 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();
}
}
}
}
我用的是雪豹。
The following piece of code observed under JConsole shows a constant increase of the heap size. The heap reach a maximum of 25mb and then the GC runs and decease the heap size to almost 3MB. Is this the expected behavior ? I'm very surprised!
public class Dummy {
public static void main(String[] args) {
System.out.println("start");
while(true){
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
I'm using Snow Leopard.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
与 jconsole 的通信导致对象被分配。我相信您在这里看到的是您的测量方法的产物。编译代码时,HotSpot 也可能会进行轻微的分配。如果您担心,请使用探查器查看正在分配的内容(再次注意探查器界面的分配)。
正常的 GC 行为是为了避免不必要的运行。您将在网络上看到内存使用情况的锯齿图。这里在缓存和交换友好性与避免工作之间存在一些折衷。此外,服务器 HotSpot 比客户端 HotSpot 更频繁地消耗内存。
Communication with jconsole causes objects to be allocated. I believe what you are seeing here is is an artifact of your measurement method. There may also be slight allocation by HotSpot when compiling code. If you are worried, use a profiler to see what is being allocated (again, watch out for allocations by the profiler's interface).
Normal GC behaviour is to avoid running unnecessarily. You will see all over the web sawtooth graphs of memory usage. There is some compromise here between cache and swap friendliness and avoiding work. Also server HotSpot is more aggressive about using up memory than the client HotSpot.
是的,这应该是预期的行为。虽然您没有执行任何特定于分配对象的操作,但 sleep 的实现可能是这样,即使没有,JVM 中也有其他线程正在运行,这很可能是这样。
Yes, this should be the expected behaviour. While you are not doing anything specific to allocate objects, the implementation of sleep might be, and even if that doesn't, there are other threads running in the JVM, that could well be.
是的,这很正常。您没有显式创建任何对象,但您正在调用可能创建一些临时对象作为其实现的一部分的方法。这些临时对象会堆积起来,直到 GC 运行将其清除为止。
Yes, it's normal. You're not explicitly creating any objects, but you're calling methods that probably create some temporary objects as part of their implementation. Those temporary objects pile up until it's time for a GC run to clean them out.
类文件看起来像这样,代码从 8 循环到 14,java.lang.Thread.sleep() 是原生的。因此,没有理由创建 MB 的对象,
恐怕您看到的是来自 JProfiler 本身(我不知道您如何将其附加到虚拟测试应用程序)或在此虚拟机中运行的其他内容。要找出已创建的对象,如果 JProfiler 未显示此信息,您应该执行堆转储。
'
The class files looks like that, the code loops from 8 to 14, and java.lang.Thread.sleep() is native. Therefore there is no reason to create MB's of objects
I'm afraid what you see is from JProfiler itself (I don't know how you attached it to your Dummy test app) or other things running in this vm. To find out what objects have been created you should do a heap dump if JProfiler doesn't show this information.
'
关于其原因显然有两种理论,并且不可能根据经验推理来区分它们。我可以建议一个简单的实验吗?
将程序更改为休眠 1 毫秒而不是 5000。(实际数字并不重要...这是为了使假设的内存分配尽可能快地发生。您也可以尝试 0 毫秒,但行为睡眠时间可能会有所不同...)
使用当前方法运行程序;例如使用 jconsole。
在没有 jconsole 等的情况下运行程序,但使用“-verbose:gc”选项,以便您可以看到 GC 何时运行。
在
我怀疑在最后一种情况下,您会失去耐心等待 GC 运行......甚至尽可能快地调用
sleep
。There are clearly two theories as to the cause, and it is not possible to distinguish them based on empirical reasoning. Can I suggest a simple experiment.
Change the program to sleep for 1 millisecond instead of 5000. (The actual number doesn't matter ... this is to make the hypothesized memory allocation happen as fast as possible. You could also try 0 milliseconds, but the behaviour of sleep may well be different ...)
Run the program using the current approach; e.g. with jconsole.
Run the program without jconsole, etc, but with the "-verbose:gc" option so that you can see when the GC runs.
I suspect that you will run out of patience waiting for the GC to run in the last case ... even calling
sleep
as fast as possible.