import javax.swing.*;
import java.awt.event.*;
import java.awt.FlowLayout;
import java.awt.Dimension;
import java.lang.String;
import javax.swing.JOptionPane;
import java.awt.Container;
import java.util.Hashtable;
import java.awt.BorderLayout;
import java.awt.Component;
import javax.swing.DefaultListCellRenderer;
import javax.swing.border.Border;
import javax.swing.border.EmptyBorder;
class ComboBoxRenderer
    implements ListCellRenderer {  public ComboBoxRenderer() {
      }  public Component getListCellRendererComponent(
      JList list,
      Object value,
      int index,
      boolean isSelected,
      boolean cellHasFocus) {
    JLabel itemLabel = new JLabel(value);
    JPanel itemPanel = new JPanel();
    itemPanel.setToolTipText(sValue);
    itemPanel.setSize(list.getSize().width, 25);
    itemPanel.setLayout(new BorderLayout());
    itemPanel.add(itemLabel, BorderLayout.WEST);
    if (isSelected || cellHasFocus) {
      itemPanel.setForeground(list.getSelectionForeground());
      itemPanel.setBackground(list.getSelectionBackground());
    }
    else {
      itemPanel.setForeground(list.getForeground());
      itemPanel.setBackground(list.getBackground());
    }
    return itemPanel;
  }
}
public class test extends JFrame{
    JComboBox select=null;
    JButton button=null;
    consuMem mem=null;
    String preItem=null;
    Hashtable sessionTable=new Hashtable();
    public test(String title) {
        super(title);
        setSize(new Dimension(200,100));
        getContentPane().setLayout(new FlowLayout());
        addWindowListener(
                new WindowAdapter() {
            public void windowClosing(WindowEvent e) {
                System.exit(0);
            }        });
        select=new JComboBox();
        select.setRenderer(
        new ComboBoxRenderer(ComboBoxRenderer.COMBOTYPE_TEMPLATE));
        for (int i=0;i<200;i++) {
            select.addItem(String.valueOf(i));
         }
        select.addActionListener(new ActionListener() {
            public void actionPerformed(ActionEvent e){
                
            }
        });
        getContentPane().add(select);    }
    public static void main(String[] args) {
        sessionWindow swindow=null;
        test test1=new test("MainWindow");
        test1.show();
    }
}
以上程序主要是自己实现一个ListCellRenderer类,调试,用键盘在combobox的item中反复上下切换,观察内存继续增长,怀疑是    JLabel itemLabel = new JLabel(value);
                                JPanel itemPanel = new JPanel();
这两句的问题,因为它们每次都会分配新的对象,于是将ComboBoxRenderer类改为如下形式:
class ComboBoxRenderer
    implements ListCellRenderer {
  public static JLabel itemLabel = new JLabel();
  public static JPanel itemPanel = new JPanel();
  private int type_;  public ComboBoxRenderer(int type) {
    
  }  public Component getListCellRendererComponent(
      JList list,
      Object value,
      int index,
      boolean isSelected,
      boolean cellHasFocus) {
    if (value == null) {
      return null;
    }
    itemLabel.setText(value);
    itemPanel.setToolTipText(sValue);
    itemPanel.setSize(list.getSize().width, 25);
    itemPanel.setLayout(new BorderLayout());
    itemPanel.add(itemLabel, BorderLayout.WEST);
    if (isSelected || cellHasFocus) {
      itemPanel.setForeground(list.getSelectionForeground());
      itemPanel.setBackground(list.getSelectionBackground());
    }
    else {
      itemPanel.setForeground(list.getForeground());
      itemPanel.setBackground(list.getBackground());
    }
    return itemPanel;
  }
}
发现不会出现上面的现象了。但是我不大理解为什么会这样,按道理说,JVM每次getListCellRendererComponent()绘制完后,对它们的引用就会消失,内存也会被回收,为什么会出现上面的现象内,哪位大侠能够给解释一下,谢谢了

解决方案 »

  1.   

    jvm 隔一段时间才作一次GC, 所以引用释放之后,对象所占的内存不会马上释放掉。
      

  2.   

    但是隔一段时间是多长呢?我等了很长时间也没有见回收啊
    我的理解是,对ListCellRender是不是根本就不回收。
    也就是说
    1.MainFrame中Combox初始化时,会调用getListCellRenderer()获取combox item的render进行绘制(最典型的就是renderer是JLabel的一个子类),
    2.当用户选择combox出现下拉框时,也会调用此方法进行绘制
    3.当combox失去焦点时,绘制完成的JLabel只是隐藏(或者被其他的component所覆盖),而不是被dispose,所以不会被回收,否则根本无法解释上面的代码会出现OutOfMemory Error.还望GUI高手给解释解释啊,谢谢了