使用 JTextPane 时如何防止内存泄漏?
How do I prevent Memory leaks when using JTextPane?
我有一个包含按钮的 JFrame
。单击该按钮时,它会打开一个 window,其中包含一个带有大量文本的 JTextPane
。
- 一开始,应用程序占用了 35 MB 的内存。
- 打开新 window 时,应用程序占用大约 200 MB 的内存。
- 关闭新 window 时,应用程序占用大约 120 MB 的内存。
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();
}
}
我已经覆盖了 dispose 方法以将此 JTextPane
设置为 null。我预计内存消耗会下降到 35 MB,但它下降到只有 120 MB。为什么会这样? JTextPane
中的字符串是否未被垃圾收集?
我如何确保在使用 JTextPane
时释放内存?
编辑:
我在 Windows 10 上使用 jdk 16 来测试这个,我在任务管理器
上看到了内存使用情况
不要期望 System.gc() 强制执行 gc。有些 jvm 在被调用时甚至什么都不做。只要它决定,jvm 就可以执行 gc。
嗯,看起来没有发生内存泄漏。
运行 jconsole 下的程序显示关闭新 windows:
后堆内存确实 return 到原始大小
但是,当创建第一个 window 时,非堆内存显着增加:
即使在创建第二个 window 甚至第三个后,非堆内存也几乎保持不变,所以我想这里没有太大问题。
我不知道有什么方法可以释放 non-heap 内存,但我想可以肯定地说上面的代码是正确的,并且没有发生内存泄漏。
(虽然只有最后一个 System.gc() 调用就足够了)
我有一个包含按钮的 JFrame
。单击该按钮时,它会打开一个 window,其中包含一个带有大量文本的 JTextPane
。
- 一开始,应用程序占用了 35 MB 的内存。
- 打开新 window 时,应用程序占用大约 200 MB 的内存。
- 关闭新 window 时,应用程序占用大约 120 MB 的内存。
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();
}
}
我已经覆盖了 dispose 方法以将此 JTextPane
设置为 null。我预计内存消耗会下降到 35 MB,但它下降到只有 120 MB。为什么会这样? JTextPane
中的字符串是否未被垃圾收集?
我如何确保在使用 JTextPane
时释放内存?
编辑: 我在 Windows 10 上使用 jdk 16 来测试这个,我在任务管理器
上看到了内存使用情况不要期望 System.gc() 强制执行 gc。有些 jvm 在被调用时甚至什么都不做。只要它决定,jvm 就可以执行 gc。
嗯,看起来没有发生内存泄漏。 运行 jconsole 下的程序显示关闭新 windows:
后堆内存确实 return 到原始大小但是,当创建第一个 window 时,非堆内存显着增加:
即使在创建第二个 window 甚至第三个后,非堆内存也几乎保持不变,所以我想这里没有太大问题。
我不知道有什么方法可以释放 non-heap 内存,但我想可以肯定地说上面的代码是正确的,并且没有发生内存泄漏。 (虽然只有最后一个 System.gc() 调用就足够了)