我知道session.invalidate()
释放httpsession。但是当我监视容器内存时,它并没有下降。这是我正在观察的 -
- 登录(我的应用程序创建一个会话)
- 用户执行一些增加进程内存的活动。
- 登出。(注销控制器显式地使会话无效)
- 监控进程内存。它永远不会下来。
最初我认为,垃圾收集可能只有在达到低内存可用状态后才能工作。为了确认这一点,我使用 -Xmx 来减少内存。但仍然是同样的错误。事实上,当我使用单独的浏览器执行相同的活动时,我看到了 OOM 错误。
这里有什么遗漏吗?
我知道session.invalidate()
释放httpsession。但是当我监视容器内存时,它并没有下降。这是我正在观察的 -
最初我认为,垃圾收集可能只有在达到低内存可用状态后才能工作。为了确认这一点,我使用 -Xmx 来减少内存。但仍然是同样的错误。事实上,当我使用单独的浏览器执行相同的活动时,我看到了 OOM 错误。
这里有什么遗漏吗?
您可以尝试以下方法之一来分析问题:
打印 GC 日志并查看是否发生了多少次 Young/Full GC 收集:
-XX:+UnlockDiagnosticVMOptions -XX:+LogVMOutput -XX:LogFile=jvm.log -XX:+HeapDumpOnOutOfMemoryError -Xloggc:bin/gc.log -XX:+PrintGCTimeStamps -XX:+PrintGCDetails -verbose:gc
检查 Class Histograms 以查看您的类的实例是否正在被 Full GC 收集。比较 Full GC 之前/之后的实例数。使能够 :
-XX:+PrintClassHistogramBeforeFullGC -XX:+PrintClassHistogramAfterFullGC
拍摄直方图快照,再次查看是否正在收集类:
jmap -histo $pid
查看该类是否包含 finalize() 方法,该方法将阻止在 GC 期间收集对象。
正如 GargantuChet 建议的那样,收集 HeapDump 并查看哪些对象正在引用您的类实例。
它将一直存在于内存中,直到垃圾收集器运行并找到未引用的对象并清理它们。出于测试目的,您可以尝试使用System.gc()
after显式调用 GC。session.invalidate()
同样调用System.gc()
不需要调用 GC,因为 jvm 将决定是否运行 GC。