我有一个运行在oracle java虚拟机上的Ubuntu服务器上设置的glassfish v4.0,jvm进程常驻内存大小(通过“top”命令)成长,直到jvm没有内存来创build新线程。
我拥有的:
有什么问题:
RAM使用率(res memory)一直在增长,具体取决于每小时10-100m的使用率,直到jvm无法分配本地内存。
我试过了什么:
我想让我的JVM稳定,因为我测量堆空间+ perm gen只需要400-600 mb,而“top”命令显示java进程内存增长到850mb,然后杀死它自己。 我知道JVM需要更多的内存空间和堆,但是你认为我还是给堆空间和perm gen留下了太多的内存吗? 任何帮助或指导将不胜感激。
日志输出: http ://pakers.lv/logs/hs_err_pid970.log所有JVM flgas: http ://pakers.lv/logs/jvm_flags.txt
更新
我还尝试了什么(根据build议和我自己的发现):
当前状态通过这些更改,我最终限制了作为我的目标的java进程的驻留内存(内存使用量)。 在我的情况下,512m的堆空间+128m的perm gen space导致了java进程中常驻内存750m左右的稳定。 即使我仍然有内存问题 – 堆内存不时得到充分,并导致Web应用程序冻结,由于继续垃圾收集,但操作系统不杀死进程。 所以我现在需要增加系统的可用内存(RAM),或者检查堆的使用情况,降低应用程序的占用空间。 由于我的Web应用程序是基于Java EE的(使用EJB),因此我可能无法大幅减less它。 无论如何感谢您的build议,并随时分享任何其他build议,如果有的话。
给出你分享的内容有几种可能性,例如:
但我只能猜测,因为您没有提供任何日志输出,或者指出JVM是否抛出了OutOfMemoryException (OOM),或者是否遇到其他错误。 你也没有提到垃圾收集器在使用什么,但是如果上面显示的标记是唯一使用的JVM选项,那么它就是CMS收集器。
第一步是通过添加这些标志来使垃圾收集器的操作可观察:
-XX:+PrintTenuringDistribution -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -XX:+HeapDumpOnOutOfMemoryError -Xloggc:/path/to/garbage.log
如果它确实是一个OOM,你可以使用VisualVM或类似工具分析堆转储。 我也使用VisualVM通过JMX原位监视GC操作。 通过这些JVM标志可以启用对JVM内部的可见性:
-Dcom.sun.management.jmxremote -Dcom.sun.management.jmxremote.port=4231 -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.authenticate=false
日志确实有帮助。 谢谢。 那个特定的日志显示它在物理内存耗尽之前可能会增长到最大configuration。 它试图malloc〜77M,只有〜63M物理左:
本地内存分配(malloc)未能分配77873152字节提交保留内存。
..
/ proc / meminfo:MemTotal:1018724 kB MemFree:63048 kB
这是我会做的:
减less堆,使其“适合”在机器上。 将最小和最大堆设置为相同的值,以便可以判断它是否会立即适合 – 如果不适合,它将不会启动。
你可以减lessJava堆栈的大小( -Xss ),但是这个东西似乎并没有-Xss很多的线程,所以节省的空间不会超过1Mb。 我认为64位Linux的默认值是256k。 减less太多,它会启动堆栈分配的OOM。
重复testing。
当它在负载下运行一会儿时,使用jmap -dump:file=path_to_file <pid>产生按需堆转储以进行差异诊断。
其中一件事应该发生:(a)如果发生泄漏,最终会再次失败,但是OOM的types应该是不同的,或者(b)没有泄漏使得GC更加努力地工作,你完成了。 鉴于你之前曾经尝试过,前一种情况很可能,除非你减小的最大尺寸也不适合。
如果它没有OOM,比较两个转储,看看使用jhat或其他堆分析器增长。
祝你好运!
尝试通过将-D64添加到JVM启动标志来以64位模式运行进程。
您可以运行pmap $JVMPID来查看虚拟内存是如何分配的。 在崩溃之前运行它。