我们的一个SAP系统(PI ABAP + JAVA栈)正在给性能带来问题。 为机器configuration的整个64GB被占用(以及8个内核)。 每个人都怀疑java部分,但我认为不同。
java服务器节点重新启动时出现内存不足错误。 看看hprof文件,我发现它们只有1.2G(平均3个服务器节点)大小,当为服务器节点configuration3GB(-Xms和Xmx)的堆时。 这个观察导致了下面的疑问。
我已经读过,当Xms和Xmx设置为相同的值时,jvm在启动时被分配整个堆。 如果是这样的话,服务器节点从一开始就有3GB的堆。 如果是这样,为什么它不反映在hprof文件中,或者如果hprof在运行时只包含分配给对象的内存,那么这个大小显然意味着堆内存是空闲的(大于50%),所以OOM如何出错。 .. !! ??
我也知道linux会做一些所谓的内存过度提交。 即内存实际上并没有被要求时,但实际使用时。 这是造成内存不足的例外吗? 就像JVM启动时一样,操作系统对它说,你已经分配了3GB的内存,但实际上是将其延迟到实际需要的时候。 当jvm实际上试图将内存分配给对象时,其他一些应用程序可能已经耗尽了内存。 这可能吗…??
即使java节点有内存泄漏的问题,也不会局限于3GB的堆。 怎么能整个物理内存的64G ….?
还有一件事我观察到交换空间只有50%被使用。
任何光在这个…!
SAP OSS也在研究这个问题。 今天我收到了他们的回复。 我的观察是正确的。 Java并不是罪魁祸首。 ABAP堆栈正面临着一些问题,而不是释放内存。 重启ABAP工作进程后,内存在操作系统级别发布。
但是我也想了解问题的突出部分,比如是否会出现这样的情况,导致JAVA OOM错误… ?? .. 任何有关这方面的信息都会有所帮助。
在启发式模式下,在Linux上默认启用Overcommit。 这意味着内核通常会允许过度使用,这意味着它会承诺为所有进程请求更多的内存,然后实际上可以交付,希望进程永远不会真正开始同时使用所有的内存。 也许overcommit在您的服务器上被禁用,您可以通过运行来检查它:
$ cat /proc/sys/vm/overcommit_memory
如果该值为0,则启用超量使用。
如果出现实际的内存使用增长超过系统可以提供的RAM数量的情况,内核将激活OOM杀手,这将尝试杀死进程以释放内存。 它通常会杀死消耗大量内存的最年轻的进程,但是您不能依赖它。 它可以(也将会)造成严重破坏。 您可以通过调整/ proc // oom_adj(例如,如果您想避免OOM杀死数据库或其他大型RAM [ab]用户的情况)来修改OOM的亲和性以杀死特定进程。
所以,如果你的系统进入OOM阶段,对于Java进程的后果可能是他们被瞬间杀死 – 这不会让你在你正在观察的java日志中出现“内存不足”的消息。
将Xmx和Xms设置为相同的值将防止堆大小调整,但这并不意味着java进程将在启动时立即开始全部使用所有内存。 它将分配尽可能多的VIRT内存,但驻留数据集不会长到Xms,但会保持尽可能低。
在虚拟内存方面:内核将承诺(overcommit)到java进程尽可能多的(Xmx +一些额外的),但所有的内存不会立即分配。 当前数据所需的金额将仅被分配,并且您可以通过观察驻留集大小(任务已使用的非交换物理内存)来查看多less。 要查看VIRT和RSS大小,您可以运行以下命令:
$ ps aux | egrep '(^USER|java)' USER PID %CPU %MEM VSZ RSS TTY STAT START TIME COMMAND tomcat 10229 21.5 9.1 6813688 548344 ? Sl 09:01 1:10 ....java...
很可能,你正在观察的错误表明在java虚拟机进程下运行的程序没有堆空间。 尝试增加Xmx设置并重新testing您的应用程序。