[ 
https://issues.apache.org/jira/browse/ODFTOOLKIT-300?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=14900708#comment-14900708
 ] 

surfx edited comment on ODFTOOLKIT-300 at 9/25/15 3:31 PM:
-----------------------------------------------------------

[25/Sep/15] Bom a solução mais rápida para este problema seria se o 
desenvolvedor criasse um método clearRepository, na classe SelectionManager, 
deixando a mesma pública, desta forma:

clase Selection (package br.gov.serpro.requer.core.odf), subclasse public 
static class SelectionManager (deixe-a como pública)

Método:

                public static void clearRepository() {
                        repository.clear();
                }

....

Para resolver este problema, importamos todas as seguintes classes em nosso 
projeto:

CellSelection
FieldSelection
GerarAcordao2
ImageSelection
LoadObjFromOdt
Navigation
ParagraphSelection
SaveObjToOdt
Selection
TableSelection
TextDocumentSelection
TextNavigation
TextSelection

Alterando apenas a classe Selection, subclasse SelectionManager:

public static class SelectionManager { //deixe-a pública
..........
                public static void clearRepository() { //crie este método
                        repository.clear();
                }
..........


Depois no seu código basta chamar desta forma:


TextNavigation search = new TextNavigation(tag, textDocument);
while (search.hasNext()) {
    TextSelection item = (TextSelection) search.nextSelection();
    FieldSelection fieldSelection = new FieldSelection(item);
    fieldSelection.replaceWith(conteudo != null ? conteudo : "");
}
        
Selection.SelectionManager.clearRepository();




was (Author: surfx):
[25/Sep/15] Atualmente a solução abaixo apenas varre os parágrafos, ainda falta 
varrer o rodapé, cabeçalhos, tabelas e outras estruturas, caso alguém já tenha 
resolvido ou saiba como fazer, favor postar a resolução, atualmente estou 
trabalhando nesta tarefa, então assim que possível postarei a solução aqui.

Bom dia, consegui anular o problema de uso da memória, simplesmente não utilize 
o método search.nextSelection(); porque ele vai chamar o método 
Selection.SelectionManager.registerItem(mNextSelectedItem);, que vai 
incrementar a variável private static Hashtable<OdfElement, Vector<Selection>> 
repository = new Hashtable<OdfElement, Vector<Selection>>(); para sempre, pois 
nunca chama o método public static void unregisterItem(Selection item) , para 
dizer a verdade não entendi o porque da variável repository.

Para contornar, itere sobre todos os parágrafos, substitua o texto com replace 
do java e seja feliz:

        //--------------------------------------
        // Funcao replaceText
        //--------------------------------------

        public static void replaceText(TextDocument documento, String 
textoAntigo, String novoTexto){
                if (documento == null || textoAntigo == null || novoTexto == 
null) { return; }
                java.util.Iterator<Paragraph> it = 
documento.getParagraphIterator();
                if (it == null) { return; }
                while (it.hasNext()) {
                        org.odftoolkit.simple.text.Paragraph p = it.next(); if 
(p == null) { break; }
                        replaceText(p, textoAntigo, novoTexto);
                }
        }

        public static void replaceText(TextDocument documento, Map<String, 
String> chaveValor){
                if (documento == null || chaveValor == null || 
chaveValor.isEmpty()) { return; }
                java.util.Iterator<Paragraph> it = 
documento.getParagraphIterator();
                if (it == null) { return; }
                while (it.hasNext()) {
                        org.odftoolkit.simple.text.Paragraph p = it.next(); if 
(p == null) { break; }
                        for (Map.Entry<String, String> entry : 
chaveValor.entrySet()) {
                                replaceText(p, entry.getKey(), 
entry.getValue());
                        }
                }
        }
        
        public static void replaceText(Paragraph paragraph, String textoAntigo, 
String novoTexto){
                String texto = paragraph.getTextContent();
                if (textoAntigo == null || novoTexto == null) { return; }
                if (texto == null || texto.isEmpty() || 
!texto.toLowerCase().contains(textoAntigo.toLowerCase())) { return; }
                texto = texto.replace(textoAntigo, novoTexto);

                //paragraph.setTextContent(texto); //erro ! - nao use este 
metodo
                paragraph.removeTextContent();
                paragraph.getOdfElement().setNodeValue("");
                
                NodeList nodeList = paragraph.getOdfElement().getChildNodes();
                int i;
                for (i = 0; i < nodeList.getLength(); i++) {
                        Node node = nodeList.item(i);
                        if (node.getNodeType() == Node.TEXT_NODE){
                                node.setNodeValue("");
                        }else if (node.getNodeType() == Node.ELEMENT_NODE) {
                                if (node instanceof TextSpanElement)
                                        ((TextSpanElement) 
node).setTextContent("");
                        } else if (node.getNodeName().equals("text:s")) {
                                ((TextSElement) node).setTextContent("");
                        } else if (node.getNodeName().equals("text:a")) {
                                TextHyperlink.getInstanceof((TextAElement) 
node).setTextContent("");
                        }
                }
                
                paragraph.setTextContent(null);
                paragraph.setTextContentNotCollapsed(null);
                paragraph.getOdfElement().setNodeValue("");
                
                paragraph.appendTextContent(texto);
        }


Depois de substituir o texto, chame System.gc(); para liberar a memória.

> Memory Leak in ODF Simple API
> -----------------------------
>
>                 Key: ODFTOOLKIT-300
>                 URL: https://issues.apache.org/jira/browse/ODFTOOLKIT-300
>             Project: ODF Toolkit
>          Issue Type: Bug
>          Components: simple api
>    Affects Versions: 0.5-incubating
>         Environment: odfdom-java-0.8.7.jar; simple-odf-0.6.6.jar
>            Reporter: Mathias Silbermann
>            Assignee: Devin Han
>         Attachments: MemoryLeak_300.java, TestTextSelection.odt
>
>
> There is a memory leak in the ODF Simple API. I tried both, versions 0.6.6 
> and 0.6.5. It appears when running code like the examples on cookbook page
> http://incubator.apache.org/odftoolkit/simple/document/cookbook/Manipulate%20TextSearch.html
> In short, the call TextNavigation.nextSelection() leads to the leak. When you 
> look down the method's call stack, you will find that items are added to the 
> static variable "repository" of the static inner class 
> "Selection.SelectionManager". The added items are never removed from the 
> repository. One indication is that the method 
> Selection.SelectionManager.unregisterItem() is never called.
> The code works fine if text navigation is done with few documents. But when 
> its run on a server thousands of times, it will fill the JVMs memory.



--
This message was sent by Atlassian JIRA
(v6.3.4#6332)

Reply via email to