Apche POI XWPFDocument Утечка памяти

#java #apache-poi #xwpf

#java #apache-poi #xwpf

Вопрос:

Я использую Apache POI версии 5.0.0. Я использую его для создания документа Word и создания из него очень большого отчета. Apache POI занимает много памяти и после создания отчета не освобождает память.

Я не хочу увеличивать пространство кучи Java, но хочу очистить память при создании отчета. Я попытался вручную запустить сборщик мусора с помощью Visual VM, но он также не очищает память.

ниже приведен код для воспроизведения проблемы.

 package com.mi6.word;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;

import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.apache.poi.xwpf.usermodel.XWPFTable;
import org.apache.poi.xwpf.usermodel.XWPFTableRow;

public class CreateTable {

public static void main(String[] args) throws IOException, InterruptedException {
    
    XWPFDocument doc = new XWPFDocument();
    
    FileOutputStream out = new FileOutputStream(new File("createTable.docx"));
    
    int i = 0;
    
    while(i < 130000) {
        
        System.err.println("Table # "  i);
        
        XWPFTable table = doc.createTable();
        
        XWPFTableRow row = table.getRow(0);
        row.getCell(0).setText("Row 0 Col 0");
        row.addNewTableCell().setText("Row 0 Col 1");
        row.addNewTableCell().setText("Row 0 Col 2");
        
        XWPFTableRow row2 = table.createRow();
        row2.getCell(0).setText("Row 1 Col 0");
        row2.getCell(1).setText("Row 1 Col 1");
        row2.getCell(2).setText("Row 1 Col 2");
        
        XWPFTableRow row3 = table.createRow();
        row3.getCell(0).setText("Row 2 Col 0");
        row3.getCell(1).setText("Row 2 Col 1");
        row3.getCell(2).setText("Row 2 Col 2"); 
        
        i  ;
        
    }
    
    doc.write(out);
    
    doc.close();
    
    out.close();
    
    System.out.println("Create Table Write Successfully. ");
    
    //to keep alive the program to check memory is release or not. 
    while(true){
        Thread.sleep(1000);   
    }
    
}
}
 

Комментарии:

1. есть ли какая-либо разница, если вы переместите цикл занятости из контекста переменной doc?, т. Е. Попробуйте поместить код перед вложенным замыканием.

2. Я хочу повторить проблему, поэтому я создаю таблицу в большом цикле. Первоначальная проблема заключается в том, что jvm не освобождает память после вызова doc.close и out.close, память остается заполненной, а не заполняется, даже если я запускаю сборщик мусора.

3. переменная doc по-прежнему упоминается в этой области, и сборщик мусора не может ее удалить. если вы переместите предпоследнюю скобку «}» перед while (true) , сборщик мусора должен иметь возможность удалить документ. просто вызывая close, файлы хранилища / XMLBeans для выпечки не удаляются.

4. Да, вы правы, я перенес весь метод в отдельную функцию, но не в поток, и при создании документа, если я запустил gc, он очищает память.

5. Мне интересно, есть ли какой-то способ освободить память, когда мы создаем большой отчет, например, после написания около 2000 страниц.