Java内存使用,许多矛盾的数字

时间:2017-05-23 16:57:04

标签: memory java-8 playframework-2.5

我正在运行java Web应用程序的多个实例(Play Framework)。 Web应用程序运行的时间越长,重新启动Web应用程序之前可用的内存就越少。有时我得到一个OutOfMemory异常。 我试图找到问题,但是我得到了很多相互矛盾的信息,所以我找不到来源。

这是信息:

  • Ubuntu 14.04.5 LTS,内存为12 GB
  • OpenJDK Runtime Environment(build 1.8.0_111-8u111-b14-3~14.04.1-b14)
  • OpenJDK 64位服务器VM(版本25.111-b14,混合模式)

编辑: 以下是JVM设置:

  • -Xms64m
  • -Xmx128m
  • -server
  • (我不是100%确定这些参数是否正确传递给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

1 个答案:

答案 0 :(得分:4)

堆是包含Java对象的内存。 htop肯定不知道堆。正如VIRT所报告的那样,导致已用内存的因素是

  • JVM自己的代码和所需库的代码
  • 已加载类的字节代码和元信息
  • JIT编译常用方法的代码
  • I / O缓冲区
  • 线程堆栈
  • 为堆分配的内存,但当前不包含活动对象

当您转储堆时,它将包含实时Java对象,以及允许理解内容的元信息,例如类和字段名称。当工具计算使用的堆时,它将仅包含对象。所以它自然会小于堆转储文件的大小。此外,由于填充/对齐,此使用的内存通常不包含不可用的内存,此外,工具有时会假设指针大小错误,因为相关信息(32位架构与64位架构与压缩oops)不可用。堆转储。这些错误可能会加起来。

请注意,OutOfMemoryError可能还有其他原因,而不是堆中有太多对象。例如。由于内存泄漏与动态类加载或太多本机I / O缓冲区相结合,可能会有太多的元信息...