内存映射文件在应用程序结束后无法释放资源

时间:2019-02-17 11:46:17

标签: java xml jaxb nio memory-mapped-files

我用Java NIO读了大约7gb的XML文件(每个〜15kb)。并在以后使用JAXB对其进行转换。 处理完所有文件(〜12分钟)并正确关闭应用程序后,我对Windows 10机器显示的〜16GB内存消耗感到好奇。

RamMap(Sysinternals)显示,映射文件消耗了大多数文件。实际上,我的系统似乎将所有(?)处理过的文件保存在内存中。但是,此内存使用情况在Windows资源监视器可以显示给我的任何进程下列出。

但是,如果我重新启动应用程序(通过Eclipse),可以看到我的Collection仍处于相同的Object-Adress。因此,第二次运行该应用程序会将瓶颈从HDD更改为CPU。

仅当我重新启动系统时才释放内存。注销不会这样做。 由于我想对在我的计算机上使用Java进行IO的不同方法进行基准测试,因此令人不安。

我的管道在完成下一个文件夹之前先处理一个文件夹。

  1. getAllFolders收集我要处理的文件夹(〜300)
  2. getAllFilesInFolder收集其下的所有文件(〜2ká15kb)(递归)
  3. unmarshalgetAllFilesInFolder并行流收集的所有文件(〜2k)
  4. List<MyXml>转换为单个MyXml
  5. marshal MyXml
  6. 从下一个文件夹开始

以下方法处理用于解组的List<Path>的创建。

// Method returns all Folders inside the entryPath
public List<Path> getAllFolders(Path entryPath) {
    List<Path> folderList = Collections.synchronizedList(new ArrayList<Path>());
    try (DirectoryStream<Path> directoryStream = Files.newDirectoryStream(entryPath)) {
        for (Path path : directoryStream) {
            if (Files.isDirectory(path)) {
                folderList.add(path);
            }
        }
    }
    return folderList;
}

// Method returns all regular Files inside the path
public List<Path> getAllFilesInFolder(Path path){
    try (Stream<Path> files = Files.walk(path).filter(Files::isRegularFile)) {
        return files.collect(Collectors.toList());
    }
    return null;
}

单独运行这些文件大约需要2分钟,这似乎不是mmap文件很大的原因。

根源似乎在编组/解组:

public class XmlMarshaller {
    private JAXBContext jaxbContext;
    private XmlMarshaller() {
        jaxbContext = JAXBContext.newInstance(MyXml.class);
    }

    private static class LazyHolder {
        private static final XmlMarshaller INSTANCE = new XmlMarshaller();
    }

    public static XmlMarshaller getInstance() {
        return LazyHolder.INSTANCE;
    }

    public void marshal(MyXml xml, Path output) {
        try (OutputStreamWriter osw = new OutputStreamWriter(Files.newOutputStream(output), StandardCharsets.UTF_8)) {
            Marshaller marshaller = jaxbContext.createMarshaller();
            marshaller.setProperty(Marshaller.JAXB_ENCODING, StandardCharsets.UTF_8.toString());
            marshaller.setProperty(Marshaller.JAXB_FORMATTED_OUTPUT, true);
            marshaller.marshal(xml, osw);
        }
    }

    public MyXml unmarshal(Path file) {
        MyXml xml = null;
        try (InputStreamReader isr = new InputStreamReader(Files.newInputStream(file), StandardCharsets.UTF_8)) {
            Unmarshaller unmarshaller = jaxbContext.createUnmarshaller();
            xml = (MyXml) unmarshaller
                    .unmarshal(isr);
        } 
        return xml;
    }
}

我删除了catch(){...}语句以提高可读性。

我正确处理输入/输出流吗?我可以泄漏资源吗?还是Windows 10在这里进行了优化?

0 个答案:

没有答案