我们有一个Linux服务器,可以启动大约20个java程序。这些java程序都是相同的,只是它们使用的是不同的端口。这些程序运行良好。然而,过了一段时间,所有20个程序都在同一时间崩溃。这些程序中的每一个都分配了2 gig的内存,通过它们启动它们:
java -jar -Xmx 2000m
然而,据我们所知,这些节目并没有使用这些数量的记忆。整个系统有4 gig的内存。
所以问题是,java程序可能会导致所有其他9个程序崩溃吗? VM是否共享,以便在崩溃时,所有java程序都崩溃了?是否有一个日志文件我可以检查java崩溃的原因? java输出没有显示任何错误。
编辑: 奇怪的是,这发生在很长一段时间后,比如3个小时。这20个进程已经运行了相当长的一段时间,然后突然全部崩溃了。如果java运行时为每个程序启动它自己的进程,为什么它们都崩溃?
答案 0 :(得分:7)
很难准确地说出为什么java进程同时都在退出。甚至不清楚为什么他们要死了。为了诊断这些问题,我会:
转一些GC记录;例如添加“-verbose:gc”命令行选项,
确保应用程序捕获并记录可能会杀死“主”线程的异常,并
查看进程当前目录,看看它们是否正在离开崩溃转储。
但独立于此,当您运行java -jar -Xmx2000m ...
20次时,您正在查看20个OS进程,每个进程可能使用超过2Gb的虚拟内存。在具有4Gb物理内存的机器上,这简直太疯狂了。即使你有足够的交换空间(40Gb或更多)来支持那么多的虚拟内存,你也可能会在堆变得那么大之前导致虚拟内存抖动。当系统开始颠簸时,系统性能将会下降。
要避免这种情况,您需要确保系统上所有活动进程的总虚拟需求不会超过您拥有的物理内存。减少Java进程的数量,减少最大堆大小或两者。 (请记住,JVM也使用非堆内存。)
您应该考虑的另一件事是重新架构您的系统,以便它在一个JVM中使用多线程而不是使用多个JVM。如果正确实现,您应该能够在多线程体系结构中获得更多吞吐量,因为:
这可以避免拥有代码和公共数据结构的多个副本,因此您可以为有用的堆对象提供相对更多的内存,
多线程架构中的线程可以共享先前获取的对象的缓存,先前计算的值等,
单个大堆的GC比大量小堆更高效,
答案 1 :(得分:5)
如果系统只有4GB内存,你显然无法为20个进程中的每个进程分配2GB内存。即使我的水晶球现在无法访问您的日志文件,我也会认为整个系统内存不足,导致大多数正在运行的进程几乎同时崩溃。
答案 2 :(得分:3)
否 - java.exe
启动新的运行时环境。因此,如果执行20次,您将运行20个JVM,每个JVM最多允许2GB内存。由于你总共只有4GB,你很可能只是试图分配太多而耗尽内存。
答案 3 :(得分:1)
每个java程序都有自己的进程。内存中的代码将被共享(即VM二进制文件),但这应该不是问题。
您应该检查java应用程序是否因内存问题而死亡。在linux中,如果你向操作系统询问内存,它会告诉你它没问题,但实际上不会保留它。当您使用该内存时,操作系统实际上会将其从系统提取到您的进程。
可能是所有进程请求2G的情况,总共40G的内存和操作系统只允许这样做。如果进程以相同的方式运行并且它们在内存大小上不断增长,那么它们一度会达到200M大小(我忽略了其他进程和东西只是为了简化数字),并且尝试使用更多内存将会终止进程有分段错误。
现在,我不希望这会立即杀死所有应用程序,因为在第一个应用程序被终止后,操作系统将回收内存,并且它将可用于其他进程,因此它们将会死亡一个,至少1或2应该在最后活着。在一些罕见的情况下,可能是这样的情况,虽然第一个进程仍在清理之后(核心被转储,以及所有其他操作系统相关的东西......)其余的进程确实遇到了同样的问题而且它们都死了之前来自第一个的记忆实际上是可用的...但我并不认为这是一个高概率事件。
答案 4 :(得分:1)
请注意,使用-Xmx2000m启动Sun的JVM只会将堆限制为2 GB。还有其他存储区域必须是独立的大小。
所有这些系统可能同时遇到内存不足错误,并且结果都会停止。
除了Sun之外,还有JVM允许不同的内存大小调整参数;也许你更喜欢另一种JVM。
不同的Java程序以不同的方式记录它们的输出,因此如果没有更多关于该程序的知识,就不可能告诉您日志的位置。
可能存在某种输出,可能会让您了解应用程序崩溃的原因。我会通过获取启动应用程序的目录列表来查找它们。
答案 5 :(得分:0)
java -Xmx 仅确定最大堆大小。要让他们立即获得2gb,你必须使用 -Xms 。两者都是合法的,即java.-Xmx2000m -Xms2000m。输入“java -X”了解更多详情。
如果你的jvm内存不足,他们应该报告内存不足。运行它们以输出到日志。您还可以将它们设置为在死亡时运行heap dump,因为这里可能还有其他内容。
答案 6 :(得分:0)
听起来像可怕的Linux OOM Killer的工作(不,这不是一个笑话)。正如其他人所提到的那样,你可能会在盒子上分配内存,并且OOM杀手倾向于以具有大驻留内存的进程为目标(如jvm)。