Java Как удалить память в индексе Lucene, использую null, но это не приводит к результату

Я хочу создать индекс Lucene по тексту. Когда я его создаю, то выделяется память, мой тестовый метод для чтения файла и создания индекса по нему:

    @Test 
    public void testMemory() throws IOException, InterruptedException{
        
        System.out.println("start");
        
        StringBuilder sb = new StringBuilder();
        InMemoryLuceneIndex inMemoryLuceneIndex;
        //try(FileReader reader = new FileReader("E:\\Projects\\Units\\JavaQt\\Release\\v4 - ExampleTikaRubricator\\server\\in\\files\\testQueue\\bigFile.txt"))
        try(FileReader reader = new FileReader("E:\\Projects\\Units\\JavaQt\\Release\\v4 - ExampleTikaRubricator\\server\\in\\files\\testQueue\\id_14028663.TXT"))
        {
            int c;
            while((c=reader.read())!=-1){
                 
                //System.out.print((char)c);
                sb.append((char)c);
            } 
        }
        catch(IOException ex){
             
            System.out.println(ex.getMessage());
        }   
        
        System.out.println("start indexing data");
        
        for (int i = 0; i <= 5; i++) {
            System.out.println("i: "+i);
            
            //init memory
            inMemoryLuceneIndex = new InMemoryLuceneIndex(new RAMDirectory());
            
            //Create index
            inMemoryLuceneIndex.createIndex(sb.toString());
            
            //Something work
            Thread.sleep(1000);
            
            //Clear index
            inMemoryLuceneIndex.clearIndex2();
            
            //Delete link
            inMemoryLuceneIndex = null;
            
        }
        
        System.out.println("Start gc");
        
        System.gc();
        
        System.out.println("finish test");
    }

В данном примере я умышленно выполняю вызов System.gc() чтобы вызвать GC.

Код, который для создания индекса:

public class InMemoryLuceneIndex {

    private Directory memoryIndex; //В переменной сохраняется объект new RAMDirectory()

    private HashMap<String, Integer> sortIndexWord; //Для ранжирования рубрик по их весу
    
    private Analyzer customAnalyzer; //customAnalyzer без toLowerCase
    private Map<String, Analyzer> analyzers; //<Поле, Анализатор для этого поля>
    private IndexWriterConfig indexWriterConfig;
    private IndexWriter writer;
    
    public InMemoryLuceneIndex(Directory memoryIndex) throws IOException {
        super();
        this.memoryIndex = memoryIndex;
        this.analyzers = new HashMap<>();
        this.indexWriterConfig = new IndexWriterConfig(getAnalyzer());
        this.writer = new IndexWriter(this.memoryIndex, indexWriterConfig);
        this.sortIndexWord = new HashMap<>();
        
        //1) init customAnalyzer без toLowerCase
        this.customAnalyzer = CustomAnalyzer.builder()
            .withTokenizer("standard")
            .build();
        
        //2) put data in map
        this.analyzers.put("tags", new StandardAnalyzer()); 
        this.analyzers.put("tags2", customAnalyzer); 
    }

    public Directory getMemoryIndex(){
        return this.memoryIndex;
    }
    
    public void createIndex(String content) throws IOException {
        
        try {
            Document doc = new Document(); 
             
            FieldType type = new FieldType(); 
            type.setStoreTermVectors(true);
            type.setStoreTermVectorPositions(true);
            type.setStoreTermVectorOffsets(true);
            type.setStored(true);
            type.setIndexOptions(IndexOptions.DOCS_AND_FREQS_AND_POSITIONS_AND_OFFSETS);
            
            Field fieldStore = new Field("tags", content, type); 
            doc.add(fieldStore); 
            
            FieldType type2 = new FieldType();
            type2.setStoreTermVectors(true);
            type2.setStoreTermVectorPositions(true);
            type2.setStoreTermVectorOffsets(true);
            type2.setStored(false); //Это поле не будет сохраняться
            type2.setIndexOptions(IndexOptions.DOCS_AND_FREQS_AND_POSITIONS_AND_OFFSETS);
            
            Field fieldStore2 = new Field("tags2", content, type2); 
            doc.add(fieldStore2);  
            
            writer.addDocument(doc); 
        }
        catch(Exception e){
            e.printStackTrace();
        }
   }
    

    public Analyzer getAnalyzer() throws IOException {       
        return new PerFieldAnalyzerWrapper(new StandardAnalyzer(), this.analyzers);
    }


    public void clearIndex2() throws IOException{
        
        this.writer.deleteAll();
        this.writer.commit();
        this.writer.close();
        
        this.memoryIndex.close();
        
        this.indexWriterConfig = null;
        this.writer = null;
        this.analyzers = null;
        this.customAnalyzer = null;
    }

  }

При этом везде, где я смотрел написано, что для удаления выделенной памяти под индекс надо использовать связку:

   this.writer.deleteAll();
   this.writer.commit();

Я пробовал создавать RAMDirectory, MMapDirectory, при это все равно выделяется память, потом я делаю null или делаю эти 2 команды и потом просто жду очистки, но ее не происходит, тогда я вызываю специально GC и все равно не происходит удаления, видимо есть какие-то другие способы удаления этой памяти, чтобы освободить место.

При старте приложения я устанавливаю такие параметры:

-XX:+UseSerialGC 
-verbose:gc 
-XX:+PrintGCDetails

Я могу посмотреть данные, но при это в диспетчере не вижу характерных данных. Тем самым получается, что происходит выделение и GC все равно не может собрать память даже если ссылка null.

Подскажите пожалуйста, как можно освободить выделенную память на индекс? Может быть есть еще какие-то другие способы? Или возможно надо использовать как-то другой GC, подскажите пожалуйста, заранее спасибо.


Ответы (0 шт):