2017-05-23 14 views
0

我正在运行java web应用程序(Play Framework)的多个实例。 Web应用程序运行的时间越长,重新启动Web应用程序之前可用的内存就越少。有时我会遇到OutOfMemory异常。 我试图找到问题,但我得到了很多矛盾的信息,所以我无法找到源代码。Java内存使用情况,许多矛盾的数字

这是相关信息:

  • 的Ubuntu 14.04.5 LTS与GB的12 RAM
  • OpenJDK的运行时环境(建立1.8.0_111-8u111-B14-3〜14.04.1-B14)
  • OpenJDK的64位服务器VM(建立25.111-B14,混合模式)

编辑: 这里是JVM设置:

  • -Xms64m
  • -Xmx128m
  • -server
  • (我不是100%肯定,因为我使用的/etc/init.d脚本start-stop-daemon这将启动,如果这些参数正确地传递给JVM该剧剧本的框架,这将启动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”(将“Keep unreachable objects”选项设置为ON)。

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

我不认为这是与GC有关的,因为无论等待多久都无所谓,htop总是显示这个数量的内存,它永远不会下降。

事实上,我会假设我的简单应用程序不超过20MB,mabye 30MB。

我比较堆与年龄差异与Eclipse MAT 4小时的堆转储,我没有看到对象的任何显着增加。注:我添加了-XX:+HeapDumpOnOutOfMemoryError选项,但我必须等待5-7天,直到它再次发生。我希望在你帮助我解释我的电话号码时尽早找到问题。

谢谢 schube

+3

将JVM的参数添加到问题中。堆栈内存分配(-Xss),初始堆大小(-Xms),最大堆大小(-Xmx)等。请记住,Java进程的总内存不仅仅是其堆大小。此外,您不必等待几天JVM就会在OutOfMemoryError上崩溃 - 只需减小堆大小,并且它应该发生得更快。然后查看堆栈跟踪,因为它可能会提供有关代码中分配失败的线索。 – vempo

+0

您是否尝试使用像JVisualVM这样的工具来观看实时更改?虚拟机内部的哪部分内存不断增加? – cyberbrain

+0

谢谢!我添加了JVM参数。是的,我可以在之前引发OutOfMemory错误,你是对的。但如果可能的话,我想在发生问题之前找到问题。由于这是一台远程机器,因此我无法使用JVisualVM。感谢所有的投入!! – schube

回答

4

堆是包含Java对象的内存。 htop当然不知道堆。其中,有助于使用的内存,所报告的VIRT

  • 的JVM自己的代码,并且所需的库
  • 字节代码和加载的类
  • 的JIT的元信息的整理的东西经常使用的方法的代码
  • I/O缓冲区
  • 线程堆栈分配堆
  • 内存,但目前不含有活的对象

当您转储堆时,它将包含实时Java对象,以及允许了解内容的元信息,例如类和字段名称。当工具计算使用的堆时,它将只包含对象。所以它自然会小于堆转储文件的大小。此外,由于填充/对齐,这种使用的内存通常不包含不可用的内存,而且,由于相关信息(32位体系结构与64位体系结构与压缩的Oops)在该空间中不可用,所以该工具有时会假定指针大小错误堆转储。这些错误可能总结。

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

+0

你说得对,JVM也加载了东西。但他们在Play Framework网站的某个地方写道,他们的网站在内存很少的服务器上运行(据我记忆,这是64MB到72MB,目前我找不到链接)。我的应用程序更小,需要更多的内存。我想找到一些问题! – schube

+0

他们是否真的声称拥有一台运行着这台小内存*的服务器,或者是否说过他们使用*堆大小*来运行服务器?试图运行最近的只有72MB RAM的Java虚拟机将需要大量的调整,即使是一个helloworld,然后,下面有一个操作系统必须以某种方式运行... – Holger