【问题标题】:Java Memory Usage, many contradictory numbersJava 内存使用情况,许多相互矛盾的数字
【发布时间】:2017-05-24 03:40:24
【问题描述】:

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

这是信息:

  • Ubuntu 14.04.5 LTS,12 GB RAM
  • OpenJDK 运行时环境(内部版本 1.8.0_111-8u111-b14-3~14.04.1-b14)
  • OpenJDK 64 位服务器 VM(内部版本 25.111-b14,混合模式)

编辑: 以下是 JVM 设置:

  • -Xms64M
  • -Xmx128m
  • -服务器
  • (我不能 100% 确定这些参数是否正确传递给 JVM,因为我使用的是带有 start-stop-daemon 的 /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

我现在正在挑选网络应用的实例:

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

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

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

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

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

事实上,我会假设我的简单应用使用的空间不超过 20MB,也许是 30MB。

我用 Eclipse MAT 与年龄差异为 4 小时的堆转储进行比较,我没有看到对象有任何显着增加。

PS:我添加了-XX:+HeapDumpOnOutOfMemoryError 选项,但我必须等待 5-7 天才能再次发生。我希望您能帮助我解释我的数字,并早日找到问题。

谢谢你, 舒贝

【问题讨论】:

  • 将你的JVM的参数添加到问题中。堆栈内存分配 (-Xss)、初始堆大小 (-Xms)、最大堆大小 (-Xmx) 等。请记住,Java 进程的总内存不仅仅包括其堆大小。此外,您不必等待几天让 JVM 在 OutOfMemoryError 上崩溃 - 只需减少堆大小,它应该会更快地发生。然后查看堆栈跟踪,因为它可能会为您提供有关代码中分配失败的确切位置的线索。
  • 您是否尝试使用 JVisualVM 之类的工具来实时观看更改? VM 中的哪一部分内存不断增加?
  • 谢谢!我添加了 JVM 参数。是的,我可以更早地引发 OutOfMemory 错误,你是对的。但如果可能的话,我想在问题发生之前找到它。我不能使用 JVisualVM,因为这是一台远程机器。谢谢大家的意见!!
  • @schube jvisualvm 可以连接到远程主机。它还打开自动生成的堆转储 (-XX:+HeapDumpOnOutOfMemoryError) 或使用 jmap 命令。
  • 今天我用VisualVM连接到远程主机。我可以确认,我的 JVM 参数已正确传递给 JVM。此外,堆具有预期的最大大小。元空间已使用 99%。这是我的问题吗?见这里:imgur.com/a/sCGgw HTOP 仍然显示 380MB RES。谢谢!

标签: memory java-8 playframework-2.5


【解决方案1】:

堆是包含 Java 对象的内存。 htop 肯定不知道堆。 VIRT 报告的导致已用内存的因素包括

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

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

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

【讨论】:

  • 你说得对,JVM 也会加载东西。但是在他们写的 Play Framework 网站上的某个地方,他们的网站运行在一个 RAM 很少的服务器上(据我记忆,它是 64MB 到 72MB,我目前找不到链接)。我的应用程序要小得多,需要更多的内存。一定有什么问题要找!
  • 他们真的声称有一个运行着的服务器只有那么小的 RAM 还是说他们运行着那个 heap size 的服务器?尝试运行最近只有 72MB RAM 的 Java VM 需要进行大量调整,即使对于 helloworld 也是如此,然后,下面有一个操作系统必须以某种方式运行……
猜你喜欢
  • 2022-12-04
  • 2016-08-09
  • 2014-10-18
  • 1970-01-01
  • 2017-02-07
  • 1970-01-01
  • 2020-09-12
  • 2017-03-09
  • 2011-08-19
相关资源
最近更新 更多