[ 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)