【问题标题】:Memory leaking with Date and string java内存泄漏与日期和字符串 java
【发布时间】:2016-09-02 03:07:04
【问题描述】:

我正在使用以下代码在我的应用程序中设置时间部分。但是下面的代码会逐渐泄漏内存。是因为Jlabel中的setText()吗?

谁能帮我找出错误?

另外请告诉我如何在java中释放DateformatDate的内存。

    Thread th= new Thread(new Runnable() {

        public void run() {
            DateFormat dateformat_s2= null;
            Date date_int_s2=null;
            String date_time_s2=null;
            while(c==1) {  
                try {
                    Thread.sleep(50); 
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                dateformat_s2= new SimpleDateFormat("dd:MM:yyyy  HH:mm:ss");
                date_int_s2= new Date();
                date_time_s2 = dateformat_s2.format(date_int_s2);
                time_end_label.setText(""+date_time_s2);
                date_time_s2=null;
                dateformat_s2=null;
                date_int_s2=null;
            }
        }
    });

【问题讨论】:

  • "以下代码逐渐泄漏内存。"你怎么测试这个?可以打印 Full GC 后使用了多少内存吗?
  • 顺便说一句,您不应该在不同的线程上更新 GUI 组件。我建议只在 GUI 上更新。
  • 你不需要释放'dateformat'或'date'的内存。Java中的垃圾收集器会在空闲时自动排序。
  • 它是因为日期对象。当它被转换成字符串时,内存不会被 GC 释放。我该怎么做才能释放日期对象的内存

标签: java datetime memory-management memory-leaks labels


【解决方案1】:

要监控内存使用情况,您需要查看 Full GC 后使用的内存。其他任何事情都会错过,因为您将拥有可能被清理但尚未清理的对象。

注意:无需将值设置为null,因为 GC 会在您进行时清理它们。在循环中使用局部变量也会在每次迭代时有效地丢弃对象。

注意:您可以计算直到下一秒的时间,这样您就可以每秒执行一次,而不是每秒执行 20 次。

你可以像这样重写你的代码

public static void startTimer(JLabel time_end_label) {
    Thread th = new Thread(new Runnable() {

        public void run() {
            DateFormat dateformat_s2 = new SimpleDateFormat("dd:MM:yyyy  HH:mm:ss");
            while(!Thread.currentThread().isInterrupted()) {
                Date date = new Date();
                final String date_time = dateformat_s2.format(date);
                SwingUtilities.invokeLater(new Runnable() {
                    @Override
                    public void run() {
                        time_end_label.setText(date_time);
                    }
                });
                long delay = 1000 - date.getTime() % 1000;
                try {
                    Thread.sleep(delay);
                } catch (InterruptedException e) {
                    break;
                }

            }
        }
    });
    th.setDaemon(true);
    th.start();
}

但是使用摇摆定时器会更简单,因为 ActionListener 将在 GUI 事件循环线程中为您执行。

public static void startTimer(JLabel time_end_label) {
    DateFormat dateformat= new SimpleDateFormat("dd:MM:yyyy  HH:mm:ss");
    final ActionListener listener = new ActionListener() {
        @Override
        public void actionPerformed(ActionEvent e) {
            Date date = new Date();
            final String date_time = dateformat.format(date);
            time_end_label.setText(date_time);
            int delay = (int) (1000 - date.getTime() % 1000);
            new Timer(delay, this).start();
        }
    };
    new Timer(1, listener).start();
}

【讨论】:

  • 我已经尝试过了,但它不起作用。日期对象逐渐增加 4 个字节。如何解除分配。如果转换为字符串,GC 不会释放日期对象的内存。是因为参考吗
  • @Crystal_92 date 引用每次都会被丢弃,所以你的建议是不可能的。 String 不能/不能保留对 Date 对象的引用。 Date 对象是 16 - 24 个字节,而不是 4 个。在 Java 中不可能有一个使用少于 16 个字节的对象(带有字段)。
  • 那么,这里会有什么问题。此线程占用更多 RAM 空间。当我的应用程序运行大约 5 天时,应用程序被卡住了。我现在能做什么?请指导我
猜你喜欢
  • 2011-08-29
  • 2013-12-03
  • 2011-08-29
  • 2018-12-17
  • 2014-04-30
  • 1970-01-01
  • 2013-04-03
  • 1970-01-01
  • 2011-06-12
相关资源
最近更新 更多