当前位置: 首页 > 面试题库 >

具有16GB虚拟内存并不断增长的Java程序:这有问题吗?

雍光远
2023-03-14
问题内容

在Mac OSX 5.8上,我有一个Java程序可以在100%CPU上运行很长时间-
几天或更长时间(这是一个分析并发程序的模型检查器,因此或多或少会出现这种情况)。但是,如OSX的“活动监视器”中所示,其虚拟内存大小在一天左右的时间后变得巨大:现在,它已达到16GB,并且还在不断增长。物理内存使用率大致稳定在1.1GB左右。

我想知道:16 GB(并且正在增长)是否是可能会减慢我的程序速度的问题的征兆?

I start the program with "java -Xmx1024m -ea"

java version "1.6.0_24"
Java(TM) SE Runtime Environment (build 1.6.0_24-b07-334-9M3326)
Java HotSpot(TM) 64-Bit Server VM (build 19.1-b02-334, mixed mode)

感谢大家的建议。我将尝试一些答案中给出的概要分析建议,然后再返回(由于运行时间较长,可能要花一些时间)。

为了回答以下几点,模型检查器几乎不执行I /
O(仅打印语句,具体取决于调试设置)。在我使用的模式下,它没有GUI。我不是模型检查器的主要作者(尽管我已经研究了模型检查器的一些内部结构),但是我不认为它使用了JNI。[<-–编辑:这是错误的,下面的详细信息]不执行任何内存映射。另外,我也不要求Oracle
/ Sun的JVM创建很多线程(请参阅下面的说明)。

额外的虚拟内存并没有导致模型检查器死亡,但是根据打印输出的频率,随着虚拟内存使用率的增加,它逐渐越来越慢地运行。(不过,这可能是由于垃圾收集越来越多所致。)我计划星期一在Windows计算机上尝试该操作,以查看是否发生相同的问题。

一些额外的解释:我正在运行的模型检查器(JPF)本身是在Oracle /
Sun的JVM下运行的几乎完整的JVM(完全用Java编写)。当然,作为虚拟机,JPF高度专业化以支持模型检查。

这有点违反直觉,但这意味着即使我要进行模型检查的程序被设计为多线程的,就Sun的JVM而言,也只有一个线程:一个正在运行的JPF。JPF仿真程序在模型检查过程中需要的线程。

我相信斯蒂芬·C(Stephen C)指出了问题所在。Roland
Illig给了我验证的工具。我对使用JNI错了。JPF本身不使用JNI,但是它允许插件,并且JNI已被配置的插件之一使用。幸运的是,我可以使用等效的纯Java插件。初步使用其中之一表明在最近几个小时内虚拟内存没有增长。感谢大家的帮助。


问题答案:

我怀疑这也是泄漏。但这不能是“普通”内存的泄漏,因为-Xmx1024m选项限制了普通堆的容量。同样,这不会是“
permgen”堆的泄漏,因为permgen的默认最大大小很小。

因此,我怀疑这是以下之一:

  • 您正在泄漏线程;即线程正在创建但没有终止。它们可能未处于活动状态,但是每个线程都有一个堆栈段(默认为256k至1Mb,具体取决于平台),该段未在常规堆中分配。

  • 您正在泄漏直接映射的文件。这些映射到由OS在常规堆之外分配的内存段。(@bestsss建议您查找泄漏的ZIP文件句柄,我认为这是其中的一个子案例。)

  • 您正在使用一些泄漏内存分配的内存或类似内存的JNI / JNA代码

无论哪种方式,内存分析器都有可能隔离问题,或者至少消除某些可能性。

JVM内存泄漏也是可能的,但是开始怀疑JVM是不明智的,直到您明确消除了正在使用的自己的代码和库/应用程序中的可能原因。



 类似资料:
  • 问题内容: 我在Google和此站点中搜索了我的问题,但我仍然不明白该解决方案。 我有一段程序里面有一些数据。程序在大型阵列上崩溃,并显示虚拟内存不足的错误,因此我开始考虑文件。 在此之前: 之后: 我在Ubuntu上进行了测试,并通过系统监视器看到了这种内存增加。但是我很困惑,(和)参数没有变化。 问题是-实际内存使用量的指标是什么? 这是否表示真实指标是?(并且仅分配但仍未使用的内存) 问题答

  • 本文向大家介绍解决TensorFlow训练内存不断增长,进程被杀死问题,包括了解决TensorFlow训练内存不断增长,进程被杀死问题的使用技巧和注意事项,需要的朋友参考一下 TensorFlow训练时,遇到内存不断增长,最终导致内存不足,进程被杀死。 在这里我不准备对造成这一现象的所有原因进行探讨,只是记录一下我在项目中遇到的这一问题,下面将对我遇到的内存不断增长的原因进行分析。 在Tensor

  • 问题是,那些块是什么?哪个子系统分配这些? 更新:我们不使用JIT和/或JNI本机代码调用。

  • 问题内容: 我们最近对生产系统的观察告诉我们Java容器的常驻内存使用量正在增长。关于此问题,我们已经进行了一些调查,以了解为什么Java进程使用pmap之类的本地工具会比堆+线程堆栈+共享对象+代码缓存+等消耗更多的内存。结果,我们发现本机进程(可能是malloc / mmap)分配了一些64M内存块(成对): 我将0000000720000000 3670016K的行解释为我们使用JVM参数“

  • 问题内容: 我们最近对生产系统的观察告诉我们Java容器的常驻内存使用量正在增长。关于此问题,我们已经进行了一些调查,以了解为什么Java进程使用诸如pmap之类的本地工具比堆+线程堆栈+共享对象+代码缓存+等消耗更多的内存。结果,我们发现本机进程(可能是malloc / mmap)分配了一些64M内存块(成对): 我将0000000720000000 3670016K的行解释为我们使用JVM参数

  • 问题内容: 我有一个用Golang编写的小守护程序,该守护程序可以循环运行并完成一些工作。我发现,在使用CGO_ENABLE = 1或CGO_ENABLED = 0进行编译时,守护程序的行为会有所不同。例如,在CGO_ENABLE = 1(默认设置)的情况下,程序的VSZ在短时间内(在一小时内)膨胀到1-2GB。如果CGO_ENABLED = 0,则VSZ在很长一段时间(几天内)都相同。查看以下数