我正在运行java Web应用程序的多个实例(Play Framework)。 Web应用程序运行的时间越长,重新启动Web应用程序之前可用的内存就越少。有时我得到一个OutOfMemory异常。 我试图找到问题,但是我得到了很多相互矛盾的信息,所以我找不到来源。
这是信息:
编辑: 以下是JVM设置:
start-stop-daemon
的/etc/init.d脚本启动了播放框架脚本,启动了JVM)< / LI>
这就是我如何使用它:
start() {
echo -n "Starting MyApp"
sudo start-stop-daemon --background --start \
--pidfile ${APPLICATION_PATH}/RUNNING_PID \
--chdir ${APPLICATION_PATH} \
--exec ${APPLICATION_PATH}/bin/myapp \
-- \
-Dinstance.name=${NAME} \
-Ddatabase.name=${DATABASE} \
-Dfile.encoding=utf-8 \
-Dsun.jnu.encoding=utf-8 \
-Duser.country=DE \
-Duser.language=de \
-Dhttp.port=${PORT} \
-J-Xms64M \
-J-Xmx128m \
-J-server \
-J-XX:+HeapDumpOnOutOfMemoryError \
>> \
$LOGFILE 2>&1
我现在正在选择网络应用程序的实例:
htop
显示4615M VIRT
和338M RES
。
当我使用jmap -dump:live,format=b,file=mydump.dump <mypid>
创建堆转储时,该文件只有大约50MB。
当我在Eclipse MAT中打开它时,概述显示“20.1MB”的已用内存(“Keep unreachable objects”选项设置为ON)。
那么htop中显示的338MB如何在Eclipse MAT中缩小到20.1MB?
我不认为这与GC有关,因为无论我等多久都没关系,htop总是会显示这段内存,它永远不会消失。
事实上,我认为我的简单应用程序不会使用超过20MB,mabye 30MB。
我使用Eclipse MAT与年龄相差4小时的堆转储进行比较,我没有发现对象有任何显着增加。
PS:我添加了-XX:+HeapDumpOnOutOfMemoryError
选项,但我必须等待5-7天,直到它再次发生。我希望在你帮助我解释我的数字之前找到问题。
谢谢你, schube
答案 0 :(得分:4)
堆是包含Java对象的内存。 htop
肯定不知道堆。正如VIRT
所报告的那样,导致已用内存的因素是
当您转储堆时,它将包含实时Java对象,以及允许理解内容的元信息,例如类和字段名称。当工具计算使用的堆时,它将仅包含对象。所以它自然会小于堆转储文件的大小。此外,由于填充/对齐,此使用的内存通常不包含不可用的内存,此外,工具有时会假设指针大小错误,因为相关信息(32位架构与64位架构与压缩oops)不可用。堆转储。这些错误可能会加起来。
请注意,OutOfMemoryError
可能还有其他原因,而不是堆中有太多对象。例如。由于内存泄漏与动态类加载或太多本机I / O缓冲区相结合,可能会有太多的元信息...