java - Files.getLastModifiedTime() 是否泄漏内存?

标签 java memory-leaks jvm java-8 java.nio.file

我遇到了一个错误,我们的一个服务器应用程序几乎每秒使用越来越多的内存,我设法过滤掉了一个仍然显示该行为的简短示例:

public class TestGetLastModifiedTime {
    private static final Path PATH = Paths.get("D:\\test.txt");
    private static final ScheduledExecutorService SCHEDULER = Executors.newScheduledThreadPool(1);

    public static void main(String[] args) {
        SCHEDULER.scheduleAtFixedRate(() -> getLastModifiedTime(), 0, 1, TimeUnit.SECONDS);
    }

    private static void getLastModifiedTime() {
        try {
            FileTime lastModifiedTime = Files.getLastModifiedTime(PATH);
        } catch (IOException ex) {
            throw new UncheckedIOException(ex);
        }
    }
}

在 Windows 8.1 和 Java 8u20 上运行。

通过 VisualVM,我观察到最大堆大小没有增长,并且堆本身不断增加。同时,我在 Windows 任务管理器中观察到生成的 java.exe 进程每秒都在使用(保留)更多内存。

有趣的是,当我从 VisualVM 中执行 GC 时,所有已用堆内存都被重置为几乎为零,并且 java.exe 进程的已用内存没有像预期的那样缩小,因为它被认为是保留的。

但是,GC完成后,内存使用量仍然每秒增加,而现在肯定有足够的空闲堆空间。

元空间也不受影响。

对我来说,这真的闻起来像 JVM 有内存泄漏。

谁能帮我解释一下这是怎么回事?

最佳答案

我不认为它是泄漏,原因如下:

  1. 您提到当您触发 gc 时,内存使用会回落到默认值。这不是泄漏的工作原理。当存在泄漏时,这些对象是强可达的,即使在重复垃圾回收之后,堆大小也不会显着减少。
  2. 不断增长的堆并不意味着泄漏。它也可能真的意味着创建了太多对象。这是正常的,完全没问题。在您的情况下,因为它在循环中被调用。是的
  3. 在我的机器上,java -Xmx20M TestGetLastModifiedTime 在我终止进程之前完美运行了 10 分钟。如果有泄漏,它最终会抛出 OutOfMemoryError 或有太多重复的 gc
  4. 如果您在 visualvm 中观察,内存消耗在 2mb 到 2.8mb 之间跃升。这几乎没有任何泄漏的嫌疑。此外,预计会有这么多内存消耗,因为 Files.getLastModifiedTime(PATH)ExecutorService 会在内部到处创建小实用程序对象。所以我觉得它非常好。

我机器上的行为:

enter image description here

重要的是,Windows 管理器显示出较高的堆使用率。这是很有可能。如果需要,JVM 可以预留空间。 与进行 gc 相比,提高堆利用率肯定没问题。这完全有道理(当你有钱的时候,为什么要紧缩?)。

这就是为什么观察 Windows Manager/free -m 等工具不能正确地观察内部发生的事情。要快速估算,您可能需要执行以下操作:

jstat -gccapacity 9043  | tail -n 1 | awk '{ print $4, $5, $6, $10 }' | python -c "import sys; nums = [x.split(' ') for x in sys.stdin.readlines()]; print(str(sum([float(x) for x in nums[0]]) / 1024.0) + ' mb');"
# change the pid from 9043 to your jvm process id.
#jvm process id can be known by running `jcmd` command (available as part of jdk)

这仍然比 free -m/Windows Manager

给你更好的估计

关于java - Files.getLastModifiedTime() 是否泄漏内存?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27382099/

相关文章:

java - Android设备java中的串行通信

java - GSON:JSON反序列化为变量类型(List/String)

java - 广告不可见。不刷新添加。从现在开始安排广告刷新 60000 毫秒

c++ - 如何销毁 QPainter 对象/摆脱 drawText() 内存泄漏?

node.js - NodeJS + GCloud 日志记录中的内存泄漏

java - 从 JVM 调用 CLR 代码

java - 验证二维数组是否有两个相等行的算法

Delphi - 使用接口(interface)内的接口(interface)时,我出现内存泄漏,但不知道为什么

java - 尝试设置JVM标志时Java运行时崩溃

Java线程启动时间