[
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 11:14 AM:
------------------------------------------------------------
[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.
was (Author: surfx):
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)