Файл с отображенной памятью не освобождает ресурсы после завершения работы приложения - PullRequest
0 голосов
/ 17 февраля 2019

Я прочитал около 7 ГБ файлов XML (~ 15 КБ каждый) с помощью Java NIO.И преобразовать их позже с JAXB.После обработки всех файлов (~ 12 минут) и правильного закрытия приложения мне любопытно, что потребляет около 16 ГБ памяти на моем компьютере с Windows 10.

RamMap (Sysinternals) показывает, что Mapped File потребляет большинство.На самом деле мои системы хранят все (?) Обработанные файлы в памяти.Но это использование памяти перечислено под любым процессом, который Windows Resource-Monitor может показать мне.

Однако, если я перезапущу свое приложение (через Eclipse), я вижу, что мои Коллекции все еще находятся на том же объектном адресе.Поэтому запуск приложения во второй раз изменит узкое место с жесткого диска на процессор.

Память освобождается только при перезагрузке системы.Выйти не сделает этого.Так как я хочу сравнить различные способы выполнения ввода-вывода с помощью Java на моем компьютере, это вызывает беспокойство.

Мой конвейер обрабатывает одну папку полностью, прежде чем начинать со следующей.

  1. getAllFoldersчтобы собрать папки (~ 300), которые я хочу обработать
  2. getAllFilesInFolder, чтобы собрать все файлы (~ 2k á 15kb) под ним (рекурсивно)
  3. unmarshal все файлы (~2k), собранные getAllFilesInFolder в параллельном потоке
  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(){...} для лучшей читаемости.

AmЯ правильно обрабатываю потоки ввода / вывода?Могу ли я получить утечку ресурсов?Или Windows 10 здесь оптимизирует?

...