We have known, the ListCellRenderer interface has only one method public Component getListCellRendererComponent(), and it returns a Component. When a JList needs to compute its dimension or paint its cell item, this method will be called. So it will be called frequently, and we have a best practice, try to reuse object, avoid time-consumed computation and unnecessary operation in this method.
Recently found, there is a memory leak bug for list cell renderer in both JDK 1.4.x and JDK 5 (don’t know whether has the same bug in earlier JDK). The component returned from getListCellRendererComponent() method could not be GC, and all its referenced objects also could not be GC. Unfortunately, this bug is only fixed in JDK 6.
So currently, if a JList use the ListCellRenderer, but only holds a little resource (eg: the JList only has little items, and the component is returned from ListCellRenderer is a simple JLable), you may not care about the memory leak.
But if a JList use the ListCellRenderer, and holds a large resource, you should remember to use the following way to avoid memory leak.
Work Around: Subclass JList and invoke removeAll after painting is done:
public class xxxList extends JList {
private CellRendererPane renderer;
private CellRendererPane getRenderer() {
if (renderer == null) {
for (int i=0; i<getComponents().length; i++) {
Component c = getComponents()[i];
if (c instanceof CellRendererPane) {
renderer = (CellRendererPane)c;
break;
}
}
}
return renderer;
}
protected void paintComponent(Graphics g) {
super.paintComponent(g);
CellRendererPane renderer = getRenderer();
if (renderer != null) {
renderer.removeAll();
}
}
}
Please refer to http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=5044798 for more details.