removePacketListener() doesn''t remove listener

I am profiling my XMPP client looking for memory leaks. I have found that XMPPConnection.removePacketListener(PacketListener listener) does not remove the listener.

XMPPConnection.addPacketListener(PacketListener listener) calls PacketReader.addPacketListener(). PacketReader wraps the PacketListener in a ListenerWrapper object and adds this to a collection of PacketListeners. But, when removePacketListener(PacketListener listener) is called, PacketReader attempts to remove the listener and not the ListenerWrapper instance. The listener is not found and thus not removed.

Pony

Here is a work around that I coded:

/**
     * Removes a packet listener.
     *
     * @param packetListener the packet listener to remove.
     */
    public void removePacketListener(PacketListener packetListener) {
         ListenerWrapper wrapperToRemove = null;
         
         for (Iterator listenerIt = listeners.getIterator(); listenerIt.hasNext();) {
              ListenerWrapper wrapper = (ListenerWrapper) listenerIt.next();
              if (wrapper.packetListener == packetListener) {
                   cancelPacketCollector(wrapper.packetCollector);
                   wrapperToRemove = wrapper;
                   break;
              }
         }
         if (wrapperToRemove != null) {
              cancelPacketCollector(wrapperToRemove.packetCollector);
              listeners.remove(wrapperToRemove);
         }
        //listeners.remove(packetListener);
    }

Message was edited by: PouncePony

Which version of Smack are you looking at as there were some fundamental changes made recently to the PacketReader?

By the code you commented out I am going to assume it is the latest nightlies. This is the code that is called when listeners.remove() is called:

public void remove(E member) {
            synchronized (mutex) {
                for (int i = collectors.size()-1; i >= 0; i--) {
                    E element = collectors.get(i);
                    if (element != null && element.equals(member)) {
                        collectors.set(i, null);
                        nullArray[++nullIndex] = i;
                        return;
                    }
                }
            }
        }

Tracing to the ListenerWrapper#equals method:

public boolean equals(Object object) {
            if (object == null) {
                return false;
            }
            if (object instanceof ListenerWrapper) {
                return ((ListenerWrapper)object).packetListener.equals(this.packetListener);
            }
            else if (object instanceof PacketListener) {
                return object.equals(this.packetListener);
            }
            return false;
        }

As you can see the equality of the object is checked against the ListenerWrapper. I think this may have been a bug in the code at some point where it wasn’'t removed properly, so if this is the case then update but if not, are you experiencing behavior that would indicate to you otherwise?

Thanks,

Alex

I am using a nightly build from July 17th.

I looked at the PackerReader.java from the smack-dev-2006-09-22.zip build, and the code adding and removing packet listeners looks identical to the code in the July 17th build.

Pony

So then why do you think that the listeners are not being removed?

Thanks,

Alex