0

I am trying to implement a message console in swing, using a JTextPane. I found some implementation but was experiencing massive memory leaks.

II did a lot of research and made sure (at least I hope I did) to follow the AWT thread rules. I can't figure out what I am doing wrong… This includes thorough reading of a seemingly similar case:

How to prevent memory leak in JTextPane.setCaretPosition(int)?

Below is simple sample that reproduces the leak: In a swing (500 ms recurring) timer, 100 lines of text are added. Whenever there are 10000 rows, 1000 rows are removed.

Please any help solving this would be appreciated

import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.Font;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import javax.swing.*;
import javax.swing.text.BadLocationException;
import javax.swing.text.Style;
import javax.swing.text.StyleConstants;
import javax.swing.text.StyledDocument;

public class ConsoleTester {
    private int m_totalRowsNum = 0;
    StyledDocument m_document;
    String lineText = "ONCE upon a time there were four little Rabbits, and their names were— Flopsy, Mopsy, Cotton-tail, \n";
    Style styleGreen;
    private int m_docLength = 0;

    void createAndShowGUI() {
        JFrame frame;
        JTextPane textPane;
        JTextField textField;
        JScrollPane scrollPane;

        frame = new JFrame();
        frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);

        textPane = new JTextPane();
        textPane.setEditable(false);
        textPane.setFont(new Font("Courier New", Font.PLAIN, 16));
        textPane.setOpaque(false);
        m_document = textPane.getStyledDocument();

        styleGreen = textPane.addStyle("styleGreen", null);
        StyleConstants.setForeground(styleGreen, Color.green);
        StyleConstants.setBold(styleGreen, true);

        textField = new JTextField();

        scrollPane = new JScrollPane(textPane);
        scrollPane.setOpaque(false);
        scrollPane.getViewport().setOpaque(false);
        frame.add(textField, BorderLayout.SOUTH);
        frame.add(scrollPane, BorderLayout.CENTER);

        frame.getContentPane().setBackground(new Color(50, 50, 50));
        frame.setSize(660, 350);
        frame.setLocationRelativeTo(null);
        frame.setVisible(true);

        javax.swing.Timer timer = new Timer(500, new ActionListener() {
            public void actionPerformed(ActionEvent evt) {
                System.out.println("document length: " + m_docLength + " m_totalRowsNum: " + m_totalRowsNum);
                for (int i = 0; i < 100; i++) {
                    AddLine();
                }
                textPane.setCaretPosition(m_document.getLength());
            }
        });
        timer.start();
    }

    private void AddLine() {
        m_totalRowsNum++;
        try {
            if (m_totalRowsNum % 10000 == 0) {
                m_document.remove(0, 100000);
                m_docLength -= 100000;
            }
            m_document.insertString(m_docLength, lineText, styleGreen);
            m_docLength += lineText.length();
        } catch (BadLocationException e) {
            e.printStackTrace();
        }
    }

    public static void main(String[] args) {
        SwingUtilities.invokeLater(new Runnable() {
            public void run() {
                new ConsoleTester().createAndShowGUI();
            }
        });
    }
}
user4212919
  • 305
  • 1
  • 2
  • 7
  • Unrelated: please read about java naming conventions. Hungarian notation and m_somefield is like 2001 and shouldnt have a place in nowadays source code ;-) – GhostCat Jan 24 '18 at 14:43
  • This looks to be an exact duplicate of this [How to prevent memory leak in jtextpane setcaretpositionint](https://stackoverflow.com/questions/30903003/how-to-prevent-memory-leak-in-jtextpane-setcaretpositionint) you might have a look - they say its because you're using a for loop in your event dispatch thread. – JGlass Jan 24 '18 at 14:46
  • Yes, i read that link many times and could not find a solution to my issue. The case was long running processes and event handling. I could not figure out how it relates to my case – user4212919 Jan 24 '18 at 14:56
  • I'd try adding/merging @sfrutig code into your `public void actionPerformed(ActionEvent evt)` - too see if it helps, you never know it might as the original question also complained about running out of memory which is your same problem but its happening in a slightly different way. Doesnt hurt to try, you can just roll back the change if it doesnt help! – JGlass Jan 24 '18 at 16:44

0 Answers0