Memory Java内存使用率,许多相互矛盾的数字

Memory Java内存使用率,许多相互矛盾的数字,memory,java-8,playframework-2.5,Memory,Java 8,Playframework 2.5,我正在运行java web应用程序(Play Framework)的多个实例。 web应用运行的时间越长,在我重新启动web应用之前可用的内存就越少。有时我会遇到一个OutOfMemory异常。 我试图找到问题,但是我得到了很多相互矛盾的信息,所以我很难找到问题的根源 以下是信息: Ubuntu 14.04.5 LTS,带12 GB内存 OpenJDK运行时环境(构建1.8.0_111-8u111-b14-3~14.04.1-b14) OpenJDK 64位服务器虚拟机(构建25.111-b1

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

以下是信息:

  • Ubuntu 14.04.5 LTS,带12 GB内存
  • OpenJDK运行时环境(构建1.8.0_111-8u111-b14-3~14.04.1-b14)
  • OpenJDK 64位服务器虚拟机(构建25.111-b14,混合模式)
编辑: 以下是JVM设置:

  • -Xms64M
  • -Xmx128m
  • -服务器
  • (我不能100%确定这些参数是否正确地传递给JVM,因为我使用了一个/etc/init.d脚本和启动停止守护进程,启动播放框架脚本,启动JVM)
这就是我如何使用它:

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
我现在正在挑选web应用程序的实例:

htop
显示了4615M的
VIRT
和338M的
RES

当我使用
jmap-dump:live,format=b,file=mydump.dump
创建堆转储时,该文件只有大约50MB

当我在EclipseMat中打开它时,概览显示“20.1MB”的已用内存(将“保持不可访问对象”选项设置为ON)

那么,如何将htop中显示的338MB缩小到Eclipse MAT中的20.1MB呢

我认为这与GC无关,因为无论我等待多长时间,htop都会显示内存量,它永远不会下降

事实上,我会假设我的简单应用程序使用的内存不会超过20MB,也可能不会超过30MB

我将EclipseMat的堆转储与4小时的时间差进行了比较,并没有发现对象数量有任何显著增加

PS:我添加了
-XX:+heapdumponootfmemoryerror
选项,但我必须等待5-7天,直到它再次发生。我希望你能帮我解释我的数字,早点发现问题

谢谢,,
schube

堆是包含Java对象的内存
htop
肯定不知道堆的情况。如
VIRT
所述,有助于使用内存的因素包括

  • JVM自己的代码和所需库的代码
  • 加载类的字节码和元信息
  • 常用方法的JIT编译代码
  • I/O缓冲区
  • 线程堆栈
  • 为堆分配的内存,但当前不包含活动对象
当您转储堆时,它将包含实时Java对象,以及允许理解内容的元信息,如类和字段名。当工具计算使用的堆时,它将只合并对象。因此,它自然会小于堆转储文件的大小。此外,由于填充/对齐,此已用内存通常不包含不可用的内存。此外,由于堆转储中没有相关信息(32位体系结构vs 64位体系结构vs压缩的oops),因此工具有时假定指针大小错误。这些错误可以总结


请注意,
OutOfMemoryError
除了堆中有太多对象之外,可能还有其他原因。例如,由于内存泄漏和动态类加载或太多本机I/O缓冲区,可能有太多的元信息…

堆是包含Java对象的内存
htop
肯定不知道堆的情况。如
VIRT
所述,有助于使用内存的因素包括

  • JVM自己的代码和所需库的代码
  • 加载类的字节码和元信息
  • 常用方法的JIT编译代码
  • I/O缓冲区
  • 线程堆栈
  • 为堆分配的内存,但当前不包含活动对象
当您转储堆时,它将包含实时Java对象,以及允许理解内容的元信息,如类和字段名。当工具计算使用的堆时,它将只合并对象。因此,它自然会小于堆转储文件的大小。此外,由于填充/对齐,此已用内存通常不包含不可用的内存。此外,由于堆转储中没有相关信息(32位体系结构vs 64位体系结构vs压缩的oops),因此工具有时假定指针大小错误。这些错误可以总结


请注意,
OutOfMemoryError
除了堆中有太多对象之外,可能还有其他原因。例如,由于内存泄漏和动态类加载或太多本机I/O缓冲区,可能有太多的元信息…

将JVM的参数添加到问题中。堆栈内存分配(-Xss)、初始堆大小(-Xms)、最大堆大小(-Xmx)等。请记住,Java进程的总内存不仅仅由堆大小组成。此外,您不必等待几天JVM在OutOfMemoryError上崩溃——只要减小堆大小,就会更快发生。然后查看堆栈跟踪,因为它可能会为您提供有关代码中分配失败的确切位置的线索。您是否尝试使用JVisualVM之类的工具实时观察更改?虚拟机中的哪部分内存一直在增加?谢谢!我添加了JVM参数。是的,我可以在早些时候引发OutOfMemory错误,你是对的。但是如果可能的话,我想在问题发生之前找到它。我不能使用JVisualVM,因为这是一台远程机器。感谢所有的投入@schube jvisualvm可以连接到远程主机。它还可以打开自动生成的堆转储(-XX:+HeapDumpOnOutOfMemoryError)或使用jmap命令。我可以确认,我的JVM参数已正确传递给JVM。此外,堆具有预期的最大大小。元空间的使用率为99%。这是吗