【发布时间】:2016-03-29 17:58:42
【问题描述】:
我正在尝试将 69,930 个文件加载到基本文本编辑器中。这一切顺利,在它们全部加载后,内存位于非常酷的 130MB。但是,在加载高峰期间,这可能会达到最大 900MB - 1200MB。
内存全部引用Inflater#buf 字段。这仅用于将文件加载到对象模型中,然后不再使用它并且可以清除字节。
显然,额外的内存在加载后很快就被垃圾收集器清除了——所以没有内存泄漏。但是,似乎没有必要使用这么多额外的内存。
我尝试过的:
- 在关闭
ZipFile后立即调用System.gc()可以“解决”内存问题。这会导致约 75% 的线程监控时间、高 CPU 使用率和缓慢的加载时间。 - 减少线程池计数。这减少了影响(至 300MB),但加载时间显着延长。
- WeakReference
到目前为止我所拥有的:
我通过一个 4 线程计数的线程池调用负载,每个线程池执行相对简单的任务:
// Source source = ...;
final InputStream input = source.open();
// read into object model
input.close();
在这种情况下,Source 是一个 ZipFileSource,它会读取所有内容:
import java.io.IOException;
import java.io.InputStream;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
public class ZipFileSource implements Source {
private final String file;
private final String name;
private volatile ZipFile zip;
public ZipFileSource(final String file, final String name) {
this.file = file;
this.name = name;
}
@Override
public InputStream open() throws IOException {
close();
final ZipFile zipFile = new ZipFile(file);
final ZipEntry entry = zipFile.getEntry(name);
final InputStream stream = new ZipFileSourceZipInputStream(zipFile.getInputStream(entry));
this.zip = zipFile;
return stream;
}
@Override
public void close() throws IOException {
if (zip != null) {
zip.close();
zip = null;
}
}
private class ZipFileSourceZipInputStream extends InputStream {
private final InputStream stream;
ZipFileSourceZipInputStream(final InputStream stream) {
this.stream = stream;
}
@Override
public int read() throws IOException {
return stream.read();
}
@Override
public void close() throws IOException {
ZipFileSource.this.close();
stream.close();
}
}
}
我的想法有点少。我已经决定要么使用本机 zip 提取器,锁定每个 n 请求以进行 System.gc() 调用,要么只是放弃并让它做它的事情。
有没有一种方法可以在内存建立之前更有效地管理内存(需要垃圾回收调用)?
【问题讨论】:
-
首先创建较小的 zip 文件 :)
-
@EricWang 我实际上正在加载我拥有的整个 Eclipse 库。因为……为什么不呢?
-
您是否只是想让 jvm 在运行程序时使用更少的内存?还是?
-
@EricWang 我正在尝试“平衡”在加载文件期间发生的内存峰值。之后没有泄漏或内存问题。
-
在我看来,没有必要。 JVM 不会在一些内存没有使用后立即清除堆,以获得更好的性能。从图中可以看出,
minor gc或full gc由 jvm 自动执行 4 次,以在文件加载期间清理年轻代或老年代。然后你明确地调用了full gc。这不是内存泄漏。 GC会影响Java程序的正常服务,所以延迟到必要时(内存不足之前)。您可以添加更多内存,并在需要时将其分配给 Java 进程。
标签: java multithreading garbage-collection