I have a JFrame
containing a button. When the button is clicked, it opens a window containing a JTextPane
with a lot of text.
- At the begining, the application takes up 35 mb memory.
- When new window is opened, the application takes up ~200 mb worth of memory.
- When the new window is closed, the application takes up ~120 mb worth of memory.
package main;
import javax.swing.*;
import java.awt.*;
public class MemoryLeakTest {
public void start(){
JFrame frame = new JFrame();
frame.setSize(500,500);
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setLocationRelativeTo(null);
JButton button = new JButton("Create new window");
button.addActionListener(l->{
createWindow();
});
frame.add(button);
frame.setVisible(true);
}
public void createWindow(){
window w = new window();
w.setVisible(true);
}
public static void main(String[] args) {
new MemoryLeakTest().start();
}
}
class window extends JFrame {
private JTextPane textPane;
public window() {
setDefaultCloseOperation(JFrame.DISPOSE_ON_CLOSE);
setSize(500, 500);
textPane = new JTextPane();
textPane.setText(extremelyLongText());
add(textPane);
System.out.println("New window created!");
}
public String extremelyLongText() {
StringBuilder builder = new StringBuilder();
for (int j = 0; j < 1000; j , builder.append("\n"))
for (int i = 0; i < 10000; i , builder.append("a")) ;
return new String(builder);
}
@Override
public void dispose() {
super.dispose();
textPane.setText("");
System.gc();
textPane= null;
System.gc();
}
}
I have overridden the dispose method to set this JTextPane
to null. I expected the memory consumption to go back down to 35 mb, but it drops to only 120 mb. Why is this happening? Is the string in JTextPane
not getting Garbage Collected?
How do i ensure that memory is freed up whenever I use a JTextPane
?
Edit: I am using jdk 16 on Windows 10 to test this, and i am seeing the memory usage on task manager
CodePudding user response:
Don't expect System.gc() to force a gc. Some jvm's don't even do anything when it is called. The jvm is allowed to do gc whenever it it decides to.
CodePudding user response:
Well, it looks like there is no memory leak happening. Running the program under jconsole revealed that the heap memory does return to original size after closing the new windows:
However, the non heap memory increases significantly when the 1st window is created:
the non heap memory stays pretty much the same even after creating the 2nd window, or even a 3rd, so i guess there isn't much of a problem here.
I am not aware of any way to release non-heap memory, but i guess it is safe to say that the above code is correct, and there is no memory leak happening. (Although only the last System.gc() call is enough)