【发布时间】:2015-02-07 12:45:13
【问题描述】:
我遇到了一个错误,我们的一个服务器应用程序几乎每秒使用越来越多的内存,我设法过滤掉了一个仍然显示该行为的简短示例:
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 中 Perform GC 时,所有使用的堆内存都会重置为零,并且 java.exe 进程的使用内存不会像预期的那样缩小,因为它被认为是保留的。
但是,GC完成后,内存使用量仍然每秒增加,而现在肯定有足够的空闲堆空间。
元空间也不受影响。
对我来说,这真的很难闻,看起来 JVM 存在内存泄漏。
谁能帮我解释一下这里发生了什么?
【问题讨论】:
-
我认为没有抛出异常?
-
这就是垃圾回收的工作原理。该程序不断分配内存,最终变成垃圾。当它无法从空闲池中分配更多内存时,它会收集垃圾。只有在 GC 之后堆没有减少(无论是由 JVM 自动触发还是手动触发)时才会出现问题。
-
@fge 不抛出异常
-
@kdgregory 如果堆中有足够的可用空间,我认为不需要分配额外的内存
-
请将您的 lambda 与手动创建
File对象进行比较,使用File.lastModified()。
标签: java memory-leaks jvm java-8 java.nio.file