Java 文件.getLastModifiedTime()是否正在泄漏内存?
我遇到了一个bug,其中一个服务器应用程序几乎每秒都在使用越来越多的内存,我成功地筛选出了一个仍然显示这种行为的简短示例:Java 文件.getLastModifiedTime()是否正在泄漏内存?,java,memory-leaks,jvm,java-8,java.nio.file,Java,Memory Leaks,Jvm,Java 8,Java.nio.file,我遇到了一个bug,其中一个服务器应用程序几乎每秒都在使用越来越多的内存,我成功地筛选出了一个仍然显示这种行为的简短示例: public class TestGetLastModifiedTime { private static final Path PATH = Paths.get("D:\\test.txt"); private static final ScheduledExecutorService SCHEDULER = Executors.newScheduledT
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);
}
}
}
在Windows8.1和Java8U20上运行
通过VisualVM,我观察到最大堆大小没有增长,堆本身也在不断增加。同时,我在Windows任务管理器中观察到,生成的java.exe进程每秒都在使用(保留)更多内存
有趣的是,当我在VisualVM中执行GC时,所有使用的堆内存实际上都重置为零,并且java.exe进程使用的内存不会像预期的那样收缩,因为它被认为是保留的
然而,在GC完成后,内存使用率仍然每秒钟增加一次,而现在肯定有足够的可用堆空间
元空间也不受影响
对我来说,这真的很难闻,看起来JVM有内存泄漏
有人能帮我解释一下这里发生了什么吗? < P>我不认为它是漏的,原因如下:
gc
时,内存使用会回到默认值。这不是泄漏的工作原理。当存在泄漏时,这些对象是强可访问的,即使在重复垃圾收集之后,堆大小也不会显著减小java-Xmx20M TestGetLastModifiedTime
运行了10分钟,然后我终止了进程。如果有泄漏,它最终会抛出OutOfMemoryError
,或者有太多重复的gcFiles.getLastModifiedTime(PATH)
,ExecutorService
会在内部到处创建小型实用程序对象,因此预计会消耗大量内存。所以对我来说它看起来很好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)
这仍然比免费的-m
/Windows管理器给你一个更好的估计,我认为不会抛出异常?这就是垃圾收集的工作原理。程序不断分配最终变成垃圾的内存。当它无法从空闲池中分配更多内存时,它会收集垃圾。只有在GC之后堆没有减少时才会出现问题(无论是由JVM自动触发还是手动触发)@fge没有例外thrown@kdgregory如果堆中有足够的可用空间,我认为没有必要分配额外的内存。请将lambda与使用File.lastModified()
手动创建File
对象进行比较。我更多地考虑的是本机资源泄漏,当调用Files.getLastModifiedTime()
时,JVM中的底层C代码在哪里会泄漏内存,可能我的问题还不够清楚。当使用JVisuaVM
进行监视时,我猜JMX不断发送关于内存使用情况的更新的开销要比Ubuntu上一个文件的内存消耗大得多。我穿上看起来还可以。这可能是windows上的一个问题。这些东西在不同的平台上可以有不同的表现。因此,您可能仍然希望在发生以下情况时应用类似的逻辑来确认您自己:windows@Holger它也会在没有通过JVisualVM监控的情况下发生。@skiwi:我知道没有JVisualVM
,问题就存在了。我想强调的是,JVisualVM
生成的图形在试图分析这个特定问题时可能会导致错误的方向。JMX的副作用甚至可能在试图分析问题时隐藏问题…