🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

Article View: borland.public.jbuilder.java.swing
Article #12496

memory leak in swing (with example program)

#12496
From: carl
Date: Tue, 15 Dec 1998 00:00
304 lines
8485 bytes
I think that I have found a major memory leak in swing.  When a JDialog or
JFrame is created and then de referenced, the garbage collector picks it up
just fine.  When a JDialog or JFrame is created and then shown, the garbage
collector does not pick it up leading to every frame or dialog you have ever
created being in memory.

Here is the test program that shows what I am taking about.  (must be run in
JDK 1.2 because it uses weak references).  You will notice that it treats
JDialogs different than any other class so as to show the memory leak.

How the program works.

You send the name (fully qualified) of the class that you want to test (ie
java.lang.String, javax.swing.JDialog).

It creates 500 of these and puts them in an array which holds them via weak
references.

Every 50, it
  runs the garbage collector
  packs the array (removing all hollow entries)
  tests to see how many are left (there should be 0 left every time)

You will notice that with this example, there is none garbage collected when
we show the JDialog.

Enjoy,

Carl

public class TestGarbageCollector {
  public TestGarbageCollector(String[] args) {
    if (args.length == 0) {
      System.out.println("parms : [classname to create] <opt : number per
iteration> <opt :number of iterations> ");
    }

  String className = args[0];  int nbrperiteration = args.length > 1 ?
Integer.valueOf(args[1]).intValue() : 50;  int iterations = args.length > 2 ?
Integer.valueOf(args[2]).intValue() : 10;

    WeakArray weakArray = new WeakArray(false);

    Class clazz = String.class;
    try {
      clazz = Class.forName(className);
    } catch (Exception ex) {
      ex.printStackTrace();
    }
      for (int lcv = 0; lcv < iterations; lcv ++) {
        if (clazz.equals(javax.swing.JDialog.class)) {
          System.out.println("creating " + nbrperiteration + " of class " +
className);
          for (int lcv1 = 0; lcv1 < nbrperiteration; lcv1 ++) {
            try {
              javax.swing.JDialog d = new javax.swing.JDialog();
              weakArray.add(d);
              d.show();
              d.setVisible(false);
              d.dispose();
            } catch (Exception ex) {
              ex.printStackTrace();
              throw new RuntimeException(ex.toString());
            }
          }
        } else {
          System.out.println("creating " + nbrperiteration + " of class " +
className);
          for (int lcv1 = 0; lcv1 < nbrperiteration; lcv1 ++) {
            try {
              weakArray.add(clazz.newInstance());
            } catch (Exception ex) {
              ex.printStackTrace();
              throw new RuntimeException(ex.toString());
            }
          }
        }

      System.out.println("forcing garbage collection");
      System.gc();
      System.out.println("packing weak array");
      weakArray.pack();
      System.out.println("# created " + nbrperiteration * (lcv + 1) + " number
left " + weakArray.size());
    }
  }

  public static void main(String[] args) {
    new TestGarbageCollector(args);
  }
}

import java.util.*;
import java.lang.ref.*;

public class WeakArray implements List {
  private ArrayList data = new ArrayList();
  private boolean autoPack = true;

  class WeakArrayKey extends WeakReference {
    public WeakArrayKey(Object o) {
      super(o);
    }

    public boolean equals(Object o) {
      if (this.get() == null) {
        return false;
      } else {
        return this.get().equals(o);
      }
    }

  }

  public WeakArray() {
  }

  public WeakArray(boolean autoPack) {
    this.autoPack = autoPack;
  }

  public synchronized void pack() {
    Iterator i = iterator();
    while (i.hasNext()) {
      Object o = i.next();
      if (o == null) {
        i.remove();
      }
    }
  }

  public void add(int parm1, Object parm2) {
    if (autoPack)
      pack();
    data.add(parm1, new WeakArrayKey(parm2));
  }

  public boolean add(Object parm1) {
    if (autoPack)
      pack();
    return data.add(new WeakArrayKey(parm1));
  }

  public boolean addAll(int parm1, Collection parm2) {
    Iterator i = parm2.iterator();
    while (i.hasNext()) {
      add(parm1, i.next());
    }
    return true;
  }

  public boolean addAll(Collection parm1) {
    Iterator i = parm1.iterator();
    while (i.hasNext()) {
      add(i.next());
    }
    return true;
  }

  public void clear() {
    data.clear();
  }

  public boolean contains(Object parm1) {
    return data.contains(parm1);
  }

  public boolean containsAll(Collection parm1) {
    return data.containsAll(parm1);
  }

  public Object get(int parm1) {
    return ((WeakReference)data.get(parm1)).get();
  }

  public int indexOf(Object parm1) {
    return data.indexOf(parm1);
  }

  public boolean isEmpty() {
    return data.isEmpty();
  }

  public Iterator iterator() {
    class ReferenceIterator implements Iterator {
      Iterator realIterator;
      ReferenceIterator(Iterator i) {
        realIterator = i;
      }
      public boolean hasNext() {
        return realIterator.hasNext();
      }

      public Object next() {
        return ((WeakReference)realIterator.next()).get();
      }

      public void remove() {
        realIterator.remove();
      }
    }
    return new ReferenceIterator(data.iterator());
  }

  public int lastIndexOf(Object parm1) {
    return data.lastIndexOf(parm1);
  }

  class ReferenceListIterator implements ListIterator {
    ListIterator realIterator;
    ReferenceListIterator(ListIterator i) {
      realIterator = i;
    }
    public boolean hasNext() {
      return realIterator.hasNext();
    }

    public Object next() {
      return ((WeakReference)realIterator.next()).get();
    }

    public void remove() {
      realIterator.remove();
    }
    public boolean hasPrevious() {
      return realIterator.hasPrevious();
    }
    public Object previous() {
      return ((WeakReference)realIterator.previous()).get();
    }
    public int nextIndex() {
      return realIterator.nextIndex();
    }
    public int previousIndex() {
      return realIterator.previousIndex();
    }
    public void set(Object o) {
      realIterator.set(o);
    }
    public void add(Object o) {
      realIterator.add(o);
    }
  }

  public ListIterator listIterator() {
    return new ReferenceListIterator(data.listIterator());
  }

  public ListIterator listIterator(int parm1) {
    return new ReferenceListIterator(data.listIterator(parm1));
  }

  public Object remove(int parm1) {
    return data.remove(parm1);
  }

  public boolean remove(Object parm1) {
    return data.remove(parm1);
  }

  public boolean removeAll(Collection parm1) {
    return data.removeAll(parm1);
  }

  public boolean retainAll(Collection parm1) {
    return data.retainAll(parm1);
  }

  public Object set(int parm1, Object parm2) {
    if (autoPack)
      pack();
    return data.set(parm1, parm2);
  }

  public int size() {
    if (autoPack)
      pack();
    return data.size();
  }

  public List subList(int parm1, int parm2) {
    return data.subList(parm1, parm2);
  }

  public Object[] toArray() {
    Object[] os = data.toArray();
    for (int lcv = 0; lcv < os.length; lcv++) {
      os[lcv] = ((WeakReference)os[lcv]).get();
    }
    return os;
  }

  public Object[] toArray(Object[] parm1) {
    Object[] os = data.toArray(parm1);
    for (int lcv = 0; lcv < os.length; lcv++) {
      os[lcv] = ((WeakReference)os[lcv]).get();
    }
    return os;
  }
}


-----------== Posted via Deja News, The Discussion Network ==----------
http://www.dejanews.com/       Search, Read, Discuss, or Start Your Own    
Technical Details
Message-ID: <755rd6$7a2$1@nnrp1.dejanews.com>
Path: arc1-ca.pugleaf.net!unknown!not-for-mail

Show Full Headers
Complete Article Headers
X-Google-Language: ENGLISH,ASCII-7-bit
X-Google-Thread: 111d45,a78f818e9bb40f62,start
X-Google-Attributes: gid111d45,public
From: carl@oop.com
Subject: memory leak in swing (with example program)
Date: 1998/12/15
Message-ID: <755rd6$7a2$1@nnrp1.dejanews.com>
X-Deja-AN: 422490196
X-Http-Proxy: 1.0 x8.dejanews.com:80 (Squid/1.1.22) for client 208.251.55.59
Organization: Deja News - The Leader in Internet Discussion
X-Article-Creation-Date: Tue Dec 15 14:23:38 1998 GMT
Newsgroups: borland.public.jbuilder.java.swing
X-Http-User-Agent: Mozilla/4.5 [en] (X11; U; Linux 2.0.34 i686)