我目前正在调试一个导致间歇性问题的Web应用程序,尤其是当命中率很高时。当给每个新用户一个包含个性化导航菜单的会话时,我想我会试着看看会话变量需要多少内存。
在处理会话对象创建的JSP的代码部分中,我添加了以下代码:
System.gc();
long orgHeap = Runtime.getRuntime().freeMemory();
... create session variables ...
System.gc();
log.info("Heap delta: " + (Runtime.getRuntime().freeMemory() - orgHeap));
让我感到惊讶的是,添加System.gc()会破坏应用程序。它不再起作用,因为有些物体会丢失(或者看起来如此)。已初始化的值为null。当删除gc()调用时,应用程序正常工作。 gc()应该只删除已被标记为删除的对象 - 对吗?
还有其他人有类似的问题吗?
答案 0 :(得分:2)
我能想到的唯一一个案例就是如果您正在使用WeakReference s(或过期的SoftReference s,在这种情况下大致相似)引用您仍想保留的对象。可能进入GC收集能的状态的对象;但在它实际运行之前,你仍然可以通过你的参考资料与他们联系。调用System.gc()
,即使它没有任何保证语义,也可能导致收集器运行并收集所有这些弱可达对象。
但这似乎不太可能,因为
最后一点是重要的一点 - 你为什么要调用System.gc(),这几乎总是适得其反?我不相信你有合法的需要来打电话,它不会做你可以依赖的任何事情,显然它会打破你的申请。
因此,如果您的应用在没有拨打电话的情况下正常工作,那就停止制作吧。
我仍然会考虑检查你的应用程序如何组合在一起,因为这不是问题的实际原因,你可能有一个更深层次的问题,这个问题非常脆弱,只是等待你以后再打破。
编辑:另一个可能的原因可能是简单的时间安排。拨打System.gc()
可能需要花费不可忽视的时间。在此期间,其他线程可以以GCing线程不期望的方式进行并更改状态。因此,当它从呼叫返回时,世界状态打破了它的期望,因此导致逻辑错误。同样,这只是猜测,但比WeakReference更合理。
答案 1 :(得分:0)
垃圾收集永远不会删除活动对象,因此我认为您的问题出在其他地方。
正如你所说,这是负载 - “命中率很高” - 这可能是一个使用EJB错误的情况,你期望发生一些事情,因为它在低负载下这样做(比如在询问时反复获取相同的EJB)对于它)但是在高负荷下的变化(其他人得到了那个EJB,你得到另一个)。