Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>I just found a huge memory leak, so I am going to call the code that created the leak to be <em>wrong</em> and my fix that does not leak as <em>right</em>.</p> <p>Here is the old code: (This is a common pattern I have seen all over)</p> <pre><code>class Singleton { static Singleton getInstance() {...} void addListener(Listener listener) {...} void removeListener(Listener listener) {...} } class Leaky { Leaky() { // If the singleton changes the widget we need to know so register a listener Singleton singleton = Singleton.getInstance(); singleton.addListener(new Listener() { void handleEvent() { doSomething(); } }); } void doSomething() {...} } // Elsewhere while (1) { Leaky leaky = new Leaky(); // ... do stuff // leaky falls out of scope } </code></pre> <p>Clearly, this is bad. Many Leaky's are being created and never get garbage collected because the listeners keep them alive.</p> <p>Here was my alternative that fixed my memory leak. This works because I only care about the event listener while the object exists. The listener should not keep the object alive.</p> <pre><code>class Singleton { static Singleton getInstance() {...} void addListener(Listener listener) {...} void removeListener(Listener listener) {...} } class NotLeaky { private NotLeakyListener listener; NotLeaky() { // If the singleton changes the widget we need to know so register a listener Singleton singleton = Singleton.getInstance(); listener = new NotLeakyListener(this, singleton); singleton.addListener(listener); } void doSomething() {...} protected void finalize() { try { if (listener != null) listener.dispose(); } finally { super.finalize(); } } private static class NotLeakyListener implements Listener { private WeakReference&lt;NotLeaky&gt; ownerRef; private Singleton eventer; NotLeakyListener(NotLeaky owner, Singleton e) { ownerRef = new WeakReference&lt;NotLeaky&gt;(owner); eventer = e; } void dispose() { if (eventer != null) { eventer.removeListener(this); eventer = null; } } void handleEvent() { NotLeaky owner = ownerRef.get(); if (owner == null) { dispose(); } else { owner.doSomething(); } } } } // Elsewhere while (1) { NotLeaky notleaky = new NotLeaky(); // ... do stuff // notleaky falls out of scope } </code></pre>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload