diff --git a/build/build.xml b/build/build.xml index 0bf45a991..cd0e27d5b 100644 --- a/build/build.xml +++ b/build/build.xml @@ -26,36 +26,65 @@ - - + + - - - - + + + + + + + + + + + + + + + + + + + + + + + + + - - + + - - + + - - + + - + + + + + + + + + - - + + @@ -141,7 +170,7 @@ - + - + - + @@ -227,8 +256,7 @@ - - + - - - + + + @@ -269,8 +297,8 @@ - - + + @@ -288,14 +316,14 @@ - + - + @@ -306,7 +334,7 @@ - + @@ -325,7 +353,7 @@ @@ -515,43 +542,30 @@ - - - - - - - + - - - - - - - - - - - - migrating - finalizers - - - - - - - - + - - + + + + + + + + + + migrating + finalizers + + + + + - @@ -568,3 +582,7 @@ + + + + diff --git a/build/eclipse/classpath b/build/eclipse/classpath index 135c0ca29..30a67022b 100644 --- a/build/eclipse/classpath +++ b/build/eclipse/classpath @@ -33,5 +33,6 @@ + diff --git a/build/eclipse/project b/build/eclipse/project index 4d04574a8..b4051fde4 100644 --- a/build/eclipse/project +++ b/build/eclipse/project @@ -1,6 +1,6 @@ - smack-3.4.x + Smack diff --git a/build/resources/releasedocs/changelog.html b/build/resources/releasedocs/changelog.html index 96e5dd8c2..9e857550c 100644 --- a/build/resources/releasedocs/changelog.html +++ b/build/resources/releasedocs/changelog.html @@ -141,6 +141,14 @@ hr {
+

3.4.1 -- Feb 9, 2014

+ +

Bug

+
    +
  • [SMACK-540] - Memory leak in MultiUserChat +
  • +
+

3.4.0 -- Feb 2, 2014

Bug Fixes

diff --git a/experimental/source/org/jivesoftware/smackx/carbons/CarbonManager.java b/experimental/source/org/jivesoftware/smackx/carbons/CarbonManager.java index 9217860ce..dc2159925 100644 --- a/experimental/source/org/jivesoftware/smackx/carbons/CarbonManager.java +++ b/experimental/source/org/jivesoftware/smackx/carbons/CarbonManager.java @@ -16,6 +16,7 @@ package org.jivesoftware.smackx.carbons; +import java.lang.ref.WeakReference; import java.util.Collections; import java.util.Map; import java.util.WeakHashMap; @@ -51,18 +52,18 @@ public class CarbonManager { static { Connection.addConnectionCreationListener(new ConnectionCreationListener() { public void connectionCreated(Connection connection) { - new CarbonManager(connection); + getInstanceFor(connection); } }); } - private Connection connection; + private WeakReference weakRefConnection; private volatile boolean enabled_state = false; private CarbonManager(Connection connection) { ServiceDiscoveryManager sdm = ServiceDiscoveryManager.getInstanceFor(connection); sdm.addFeature(Carbon.NAMESPACE); - this.connection = connection; + weakRefConnection = new WeakReference(connection); instances.put(connection, this); } @@ -73,7 +74,7 @@ public class CarbonManager { * * @return a CarbonManager instance */ - public static CarbonManager getInstanceFor(Connection connection) { + public static synchronized CarbonManager getInstanceFor(Connection connection) { CarbonManager carbonManager = instances.get(connection); if (carbonManager == null) { @@ -99,6 +100,7 @@ public class CarbonManager { * @return true if supported */ public boolean isSupportedByServer() { + Connection connection = weakRefConnection.get(); try { DiscoverInfo result = ServiceDiscoveryManager .getInstanceFor(connection).discoverInfo(connection.getServiceName()); @@ -118,6 +120,7 @@ public class CarbonManager { * @param new_state whether carbons should be enabled or disabled */ public void sendCarbonsEnabled(final boolean new_state) { + final Connection connection = weakRefConnection.get(); IQ setIQ = carbonsEnabledIQ(new_state); connection.addPacketListener(new PacketListener() { @@ -148,6 +151,7 @@ public class CarbonManager { if (enabled_state == new_state) return true; + Connection connection = weakRefConnection.get(); IQ setIQ = carbonsEnabledIQ(new_state); PacketCollector collector = diff --git a/source/org/jivesoftware/smack/keepalive/KeepAliveManager.java b/source/org/jivesoftware/smack/keepalive/KeepAliveManager.java index 254a0419b..3560bc1c3 100644 --- a/source/org/jivesoftware/smack/keepalive/KeepAliveManager.java +++ b/source/org/jivesoftware/smack/keepalive/KeepAliveManager.java @@ -16,12 +16,12 @@ package org.jivesoftware.smack.keepalive; +import java.lang.ref.WeakReference; import java.util.Collections; -import java.util.Date; -import java.util.HashMap; import java.util.HashSet; import java.util.Map; import java.util.Set; +import java.util.WeakHashMap; import java.util.concurrent.ScheduledExecutorService; import java.util.concurrent.ScheduledFuture; import java.util.concurrent.ScheduledThreadPoolExecutor; @@ -52,7 +52,7 @@ import org.jivesoftware.smack.ping.packet.Ping; * @author Florian Schmaus */ public class KeepAliveManager { - private static Map instances = new HashMap(); + private static Map instances = Collections.synchronizedMap(new WeakHashMap()); private static volatile ScheduledExecutorService periodicPingExecutorService; static { @@ -65,7 +65,7 @@ public class KeepAliveManager { } } - private Connection connection; + private WeakReference weakRefConnection; private long pingInterval = SmackConfiguration.getKeepAliveInterval(); private Set pingFailedListeners = Collections.synchronizedSet(new HashSet()); private volatile ScheduledFuture periodicPingTask; @@ -120,40 +120,21 @@ public class KeepAliveManager { } private KeepAliveManager(Connection connection) { - this.connection = connection; - init(); - handleConnect(); - } + weakRefConnection = new WeakReference(connection); - /* - * Call after every connection to add the packet listener. - */ - private void handleConnect() { - // Listen for all incoming packets and reset the scheduled ping whenever - // one arrives. - connection.addPacketListener(new PacketListener() { - - @Override - public void processPacket(Packet packet) { - // reschedule the ping based on this last server contact - lastSuccessfulContact = System.currentTimeMillis(); - schedulePingServerTask(); - } - }, null); - } - - private void init() { connection.addConnectionListener(new ConnectionListener() { @Override public void connectionClosed() { stopPingServerTask(); + Connection connection = weakRefConnection.get(); handleDisconnect(connection); } @Override public void connectionClosedOnError(Exception arg0) { stopPingServerTask(); + Connection connection = weakRefConnection.get(); handleDisconnect(connection); } @@ -174,6 +155,25 @@ public class KeepAliveManager { instances.put(connection, this); schedulePingServerTask(); + handleConnect(); + } + + /* + * Call after every connection to add the packet listener. + */ + private void handleConnect() { + Connection connection = weakRefConnection.get(); + // Listen for all incoming packets and reset the scheduled ping whenever + // one arrives. + connection.addPacketListener(new PacketListener() { + + @Override + public void processPacket(Packet packet) { + // reschedule the ping based on this last server contact + lastSuccessfulContact = System.currentTimeMillis(); + schedulePingServerTask(); + } + }, null); } /** @@ -276,6 +276,7 @@ public class KeepAliveManager { public void run() { Ping ping = new Ping(); PacketFilter responseFilter = new PacketIDFilter(ping.getPacketID()); + Connection connection = weakRefConnection.get(); final PacketCollector response = pingFailedListeners.isEmpty() ? null : connection.createPacketCollector(responseFilter); connection.sendPacket(ping); diff --git a/source/org/jivesoftware/smackx/MessageEventManager.java b/source/org/jivesoftware/smackx/MessageEventManager.java index 900914b3d..7ad7adfeb 100644 --- a/source/org/jivesoftware/smackx/MessageEventManager.java +++ b/source/org/jivesoftware/smackx/MessageEventManager.java @@ -20,7 +20,6 @@ package org.jivesoftware.smackx; -import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.ArrayList; import java.util.Iterator; diff --git a/source/org/jivesoftware/smackx/muc/MultiUserChat.java b/source/org/jivesoftware/smackx/muc/MultiUserChat.java index db8a80f73..85d1aa8e1 100644 --- a/source/org/jivesoftware/smackx/muc/MultiUserChat.java +++ b/source/org/jivesoftware/smackx/muc/MultiUserChat.java @@ -27,6 +27,7 @@ import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.Iterator; +import java.util.LinkedList; import java.util.List; import java.util.Map; import java.util.WeakHashMap; @@ -116,12 +117,16 @@ public class MultiUserChat { // Chat protocol. This information will be used when another client tries to // discover whether this client supports MUC or not. ServiceDiscoveryManager.getInstanceFor(connection).addFeature(discoNamespace); + // Set the NodeInformationProvider that will provide information about the // joined rooms whenever a disco request is received + final WeakReference weakRefConnection = new WeakReference(connection); ServiceDiscoveryManager.getInstanceFor(connection).setNodeInformationProvider( discoNode, new NodeInformationProvider() { public List getNodeItems() { + Connection connection = weakRefConnection.get(); + if (connection == null) return new LinkedList(); List answer = new ArrayList(); Iterator rooms=MultiUserChat.getJoinedRooms(connection); while (rooms.hasNext()) { diff --git a/source/org/jivesoftware/smackx/ping/PingManager.java b/source/org/jivesoftware/smackx/ping/PingManager.java index 068206698..4c34f9223 100644 --- a/source/org/jivesoftware/smackx/ping/PingManager.java +++ b/source/org/jivesoftware/smackx/ping/PingManager.java @@ -16,6 +16,7 @@ package org.jivesoftware.smackx.ping; +import java.lang.ref.WeakReference; import java.util.Collections; import java.util.Map; import java.util.WeakHashMap; @@ -65,7 +66,7 @@ public class PingManager { }); } - private Connection connection; + private WeakReference weakRefConnection; /** * Retrieves a {@link PingManager} for the specified {@link Connection}, creating one if it doesn't already @@ -84,8 +85,8 @@ public class PingManager { return pingManager; } - private PingManager(Connection con) { - this.connection = con; + private PingManager(Connection connection) { + weakRefConnection = new WeakReference(connection); ServiceDiscoveryManager sdm = ServiceDiscoveryManager.getInstanceFor(connection); // The ServiceDiscoveryManager was not pre-initialized @@ -101,6 +102,7 @@ public class PingManager { * Sends a Pong for every Ping */ public void processPacket(Packet packet) { + Connection connection = weakRefConnection.get(); IQ pong = IQ.createResultIQ((Ping) packet); connection.sendPacket(pong); } @@ -121,7 +123,7 @@ public class PingManager { */ public boolean ping(String jid, long pingTimeout) { Ping ping = new Ping(jid); - + Connection connection = weakRefConnection.get(); try { SyncPacketSend.getReply(connection, ping); } @@ -151,6 +153,7 @@ public class PingManager { * @throws XMPPException An XMPP related error occurred during the request */ public boolean isPingSupported(String jid) throws XMPPException { + Connection connection = weakRefConnection.get(); DiscoverInfo result = ServiceDiscoveryManager.getInstanceFor(connection).discoverInfo(jid); return result.containsFeature(Ping.NAMESPACE); } @@ -165,6 +168,7 @@ public class PingManager { * @return true if a reply was received from the server, false otherwise. */ public boolean pingMyServer() { + Connection connection = weakRefConnection.get(); return ping(connection.getServiceName()); } } diff --git a/source/org/jivesoftware/smackx/receipts/DeliveryReceiptManager.java b/source/org/jivesoftware/smackx/receipts/DeliveryReceiptManager.java index 0b4a6aae6..e628b20e5 100644 --- a/source/org/jivesoftware/smackx/receipts/DeliveryReceiptManager.java +++ b/source/org/jivesoftware/smackx/receipts/DeliveryReceiptManager.java @@ -16,6 +16,7 @@ package org.jivesoftware.smackx.receipts; +import java.lang.ref.WeakReference; import java.util.Collections; import java.util.HashSet; import java.util.Map; @@ -52,7 +53,7 @@ public class DeliveryReceiptManager implements PacketListener { }); } - private Connection connection; + private WeakReference weakRefConnection; private boolean auto_receipts_enabled = false; private Set receiptReceivedListeners = Collections .synchronizedSet(new HashSet()); @@ -60,7 +61,7 @@ public class DeliveryReceiptManager implements PacketListener { private DeliveryReceiptManager(Connection connection) { ServiceDiscoveryManager sdm = ServiceDiscoveryManager.getInstanceFor(connection); sdm.addFeature(DeliveryReceipt.NAMESPACE); - this.connection = connection; + weakRefConnection = new WeakReference(connection); instances.put(connection, this); // register listener for delivery receipts and requests @@ -91,6 +92,7 @@ public class DeliveryReceiptManager implements PacketListener { * @return true if supported */ public boolean isSupported(String jid) { + Connection connection = weakRefConnection.get(); try { DiscoverInfo result = ServiceDiscoveryManager.getInstanceFor(connection).discoverInfo(jid); @@ -119,6 +121,7 @@ public class DeliveryReceiptManager implements PacketListener { DeliveryReceiptRequest drr = (DeliveryReceiptRequest)packet.getExtension( DeliveryReceiptRequest.ELEMENT, DeliveryReceipt.NAMESPACE); if (drr != null) { + Connection connection = weakRefConnection.get(); Message ack = new Message(packet.getFrom(), Message.Type.normal); ack.addExtension(new DeliveryReceipt(packet.getPacketID())); connection.sendPacket(ack);