mirror of
https://codeberg.org/Mercury-IM/Smack
synced 2024-11-29 17:52:06 +01:00
Convert Connection references to weak references
If a Manager is strong referenced from a gc root, usually the instances map, it should not hold itself a strong reference the connection in order to avoid a cycle that prevents the Connection instance from being gc'ed. SMACK-383
This commit is contained in:
parent
666f555733
commit
9c61c6c945
5 changed files with 46 additions and 35 deletions
|
@ -16,6 +16,7 @@
|
||||||
|
|
||||||
package org.jivesoftware.smackx.carbons;
|
package org.jivesoftware.smackx.carbons;
|
||||||
|
|
||||||
|
import java.lang.ref.WeakReference;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.WeakHashMap;
|
import java.util.WeakHashMap;
|
||||||
|
@ -56,13 +57,13 @@ public class CarbonManager {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private Connection connection;
|
private WeakReference<Connection> weakRefConnection;
|
||||||
private volatile boolean enabled_state = false;
|
private volatile boolean enabled_state = false;
|
||||||
|
|
||||||
private CarbonManager(Connection connection) {
|
private CarbonManager(Connection connection) {
|
||||||
ServiceDiscoveryManager sdm = ServiceDiscoveryManager.getInstanceFor(connection);
|
ServiceDiscoveryManager sdm = ServiceDiscoveryManager.getInstanceFor(connection);
|
||||||
sdm.addFeature(Carbon.NAMESPACE);
|
sdm.addFeature(Carbon.NAMESPACE);
|
||||||
this.connection = connection;
|
weakRefConnection = new WeakReference<Connection>(connection);
|
||||||
instances.put(connection, this);
|
instances.put(connection, this);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -99,6 +100,7 @@ public class CarbonManager {
|
||||||
* @return true if supported
|
* @return true if supported
|
||||||
*/
|
*/
|
||||||
public boolean isSupportedByServer() {
|
public boolean isSupportedByServer() {
|
||||||
|
Connection connection = weakRefConnection.get();
|
||||||
try {
|
try {
|
||||||
DiscoverInfo result = ServiceDiscoveryManager
|
DiscoverInfo result = ServiceDiscoveryManager
|
||||||
.getInstanceFor(connection).discoverInfo(connection.getServiceName());
|
.getInstanceFor(connection).discoverInfo(connection.getServiceName());
|
||||||
|
@ -118,6 +120,7 @@ public class CarbonManager {
|
||||||
* @param new_state whether carbons should be enabled or disabled
|
* @param new_state whether carbons should be enabled or disabled
|
||||||
*/
|
*/
|
||||||
public void sendCarbonsEnabled(final boolean new_state) {
|
public void sendCarbonsEnabled(final boolean new_state) {
|
||||||
|
final Connection connection = weakRefConnection.get();
|
||||||
IQ setIQ = carbonsEnabledIQ(new_state);
|
IQ setIQ = carbonsEnabledIQ(new_state);
|
||||||
|
|
||||||
connection.addPacketListener(new PacketListener() {
|
connection.addPacketListener(new PacketListener() {
|
||||||
|
@ -148,6 +151,7 @@ public class CarbonManager {
|
||||||
if (enabled_state == new_state)
|
if (enabled_state == new_state)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
Connection connection = weakRefConnection.get();
|
||||||
IQ setIQ = carbonsEnabledIQ(new_state);
|
IQ setIQ = carbonsEnabledIQ(new_state);
|
||||||
|
|
||||||
PacketCollector collector =
|
PacketCollector collector =
|
||||||
|
|
|
@ -16,12 +16,12 @@
|
||||||
|
|
||||||
package org.jivesoftware.smack.keepalive;
|
package org.jivesoftware.smack.keepalive;
|
||||||
|
|
||||||
|
import java.lang.ref.WeakReference;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Date;
|
|
||||||
import java.util.HashMap;
|
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
import java.util.WeakHashMap;
|
||||||
import java.util.concurrent.ScheduledExecutorService;
|
import java.util.concurrent.ScheduledExecutorService;
|
||||||
import java.util.concurrent.ScheduledFuture;
|
import java.util.concurrent.ScheduledFuture;
|
||||||
import java.util.concurrent.ScheduledThreadPoolExecutor;
|
import java.util.concurrent.ScheduledThreadPoolExecutor;
|
||||||
|
@ -52,7 +52,7 @@ import org.jivesoftware.smack.ping.packet.Ping;
|
||||||
* @author Florian Schmaus
|
* @author Florian Schmaus
|
||||||
*/
|
*/
|
||||||
public class KeepAliveManager {
|
public class KeepAliveManager {
|
||||||
private static Map<Connection, KeepAliveManager> instances = new HashMap<Connection, KeepAliveManager>();
|
private static Map<Connection, KeepAliveManager> instances = Collections.synchronizedMap(new WeakHashMap<Connection, KeepAliveManager>());
|
||||||
private static volatile ScheduledExecutorService periodicPingExecutorService;
|
private static volatile ScheduledExecutorService periodicPingExecutorService;
|
||||||
|
|
||||||
static {
|
static {
|
||||||
|
@ -65,7 +65,7 @@ public class KeepAliveManager {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private Connection connection;
|
private WeakReference<Connection> weakRefConnection;
|
||||||
private long pingInterval = SmackConfiguration.getKeepAliveInterval();
|
private long pingInterval = SmackConfiguration.getKeepAliveInterval();
|
||||||
private Set<PingFailedListener> pingFailedListeners = Collections.synchronizedSet(new HashSet<PingFailedListener>());
|
private Set<PingFailedListener> pingFailedListeners = Collections.synchronizedSet(new HashSet<PingFailedListener>());
|
||||||
private volatile ScheduledFuture<?> periodicPingTask;
|
private volatile ScheduledFuture<?> periodicPingTask;
|
||||||
|
@ -120,40 +120,21 @@ public class KeepAliveManager {
|
||||||
}
|
}
|
||||||
|
|
||||||
private KeepAliveManager(Connection connection) {
|
private KeepAliveManager(Connection connection) {
|
||||||
this.connection = connection;
|
weakRefConnection = new WeakReference<Connection>(connection);
|
||||||
init();
|
|
||||||
handleConnect();
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
|
||||||
* 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() {
|
connection.addConnectionListener(new ConnectionListener() {
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void connectionClosed() {
|
public void connectionClosed() {
|
||||||
stopPingServerTask();
|
stopPingServerTask();
|
||||||
|
Connection connection = weakRefConnection.get();
|
||||||
handleDisconnect(connection);
|
handleDisconnect(connection);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
public void connectionClosedOnError(Exception arg0) {
|
public void connectionClosedOnError(Exception arg0) {
|
||||||
stopPingServerTask();
|
stopPingServerTask();
|
||||||
|
Connection connection = weakRefConnection.get();
|
||||||
handleDisconnect(connection);
|
handleDisconnect(connection);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -174,6 +155,25 @@ public class KeepAliveManager {
|
||||||
|
|
||||||
instances.put(connection, this);
|
instances.put(connection, this);
|
||||||
schedulePingServerTask();
|
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() {
|
public void run() {
|
||||||
Ping ping = new Ping();
|
Ping ping = new Ping();
|
||||||
PacketFilter responseFilter = new PacketIDFilter(ping.getPacketID());
|
PacketFilter responseFilter = new PacketIDFilter(ping.getPacketID());
|
||||||
|
Connection connection = weakRefConnection.get();
|
||||||
final PacketCollector response = pingFailedListeners.isEmpty() ? null : connection.createPacketCollector(responseFilter);
|
final PacketCollector response = pingFailedListeners.isEmpty() ? null : connection.createPacketCollector(responseFilter);
|
||||||
connection.sendPacket(ping);
|
connection.sendPacket(ping);
|
||||||
|
|
||||||
|
|
|
@ -20,7 +20,6 @@
|
||||||
|
|
||||||
package org.jivesoftware.smackx;
|
package org.jivesoftware.smackx;
|
||||||
|
|
||||||
import java.lang.reflect.InvocationTargetException;
|
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
|
|
||||||
package org.jivesoftware.smackx.ping;
|
package org.jivesoftware.smackx.ping;
|
||||||
|
|
||||||
|
import java.lang.ref.WeakReference;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
import java.util.WeakHashMap;
|
import java.util.WeakHashMap;
|
||||||
|
@ -65,7 +66,7 @@ public class PingManager {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private Connection connection;
|
private WeakReference<Connection> weakRefConnection;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Retrieves a {@link PingManager} for the specified {@link Connection}, creating one if it doesn't already
|
* 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;
|
return pingManager;
|
||||||
}
|
}
|
||||||
|
|
||||||
private PingManager(Connection con) {
|
private PingManager(Connection connection) {
|
||||||
this.connection = con;
|
weakRefConnection = new WeakReference<Connection>(connection);
|
||||||
ServiceDiscoveryManager sdm = ServiceDiscoveryManager.getInstanceFor(connection);
|
ServiceDiscoveryManager sdm = ServiceDiscoveryManager.getInstanceFor(connection);
|
||||||
|
|
||||||
// The ServiceDiscoveryManager was not pre-initialized
|
// The ServiceDiscoveryManager was not pre-initialized
|
||||||
|
@ -101,6 +102,7 @@ public class PingManager {
|
||||||
* Sends a Pong for every Ping
|
* Sends a Pong for every Ping
|
||||||
*/
|
*/
|
||||||
public void processPacket(Packet packet) {
|
public void processPacket(Packet packet) {
|
||||||
|
Connection connection = weakRefConnection.get();
|
||||||
IQ pong = IQ.createResultIQ((Ping) packet);
|
IQ pong = IQ.createResultIQ((Ping) packet);
|
||||||
connection.sendPacket(pong);
|
connection.sendPacket(pong);
|
||||||
}
|
}
|
||||||
|
@ -121,7 +123,7 @@ public class PingManager {
|
||||||
*/
|
*/
|
||||||
public boolean ping(String jid, long pingTimeout) {
|
public boolean ping(String jid, long pingTimeout) {
|
||||||
Ping ping = new Ping(jid);
|
Ping ping = new Ping(jid);
|
||||||
|
Connection connection = weakRefConnection.get();
|
||||||
try {
|
try {
|
||||||
SyncPacketSend.getReply(connection, ping);
|
SyncPacketSend.getReply(connection, ping);
|
||||||
}
|
}
|
||||||
|
@ -151,6 +153,7 @@ public class PingManager {
|
||||||
* @throws XMPPException An XMPP related error occurred during the request
|
* @throws XMPPException An XMPP related error occurred during the request
|
||||||
*/
|
*/
|
||||||
public boolean isPingSupported(String jid) throws XMPPException {
|
public boolean isPingSupported(String jid) throws XMPPException {
|
||||||
|
Connection connection = weakRefConnection.get();
|
||||||
DiscoverInfo result = ServiceDiscoveryManager.getInstanceFor(connection).discoverInfo(jid);
|
DiscoverInfo result = ServiceDiscoveryManager.getInstanceFor(connection).discoverInfo(jid);
|
||||||
return result.containsFeature(Ping.NAMESPACE);
|
return result.containsFeature(Ping.NAMESPACE);
|
||||||
}
|
}
|
||||||
|
@ -165,6 +168,7 @@ public class PingManager {
|
||||||
* @return true if a reply was received from the server, false otherwise.
|
* @return true if a reply was received from the server, false otherwise.
|
||||||
*/
|
*/
|
||||||
public boolean pingMyServer() {
|
public boolean pingMyServer() {
|
||||||
|
Connection connection = weakRefConnection.get();
|
||||||
return ping(connection.getServiceName());
|
return ping(connection.getServiceName());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -16,6 +16,7 @@
|
||||||
|
|
||||||
package org.jivesoftware.smackx.receipts;
|
package org.jivesoftware.smackx.receipts;
|
||||||
|
|
||||||
|
import java.lang.ref.WeakReference;
|
||||||
import java.util.Collections;
|
import java.util.Collections;
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Map;
|
import java.util.Map;
|
||||||
|
@ -52,7 +53,7 @@ public class DeliveryReceiptManager implements PacketListener {
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
private Connection connection;
|
private WeakReference<Connection> weakRefConnection;
|
||||||
private boolean auto_receipts_enabled = false;
|
private boolean auto_receipts_enabled = false;
|
||||||
private Set<ReceiptReceivedListener> receiptReceivedListeners = Collections
|
private Set<ReceiptReceivedListener> receiptReceivedListeners = Collections
|
||||||
.synchronizedSet(new HashSet<ReceiptReceivedListener>());
|
.synchronizedSet(new HashSet<ReceiptReceivedListener>());
|
||||||
|
@ -60,7 +61,7 @@ public class DeliveryReceiptManager implements PacketListener {
|
||||||
private DeliveryReceiptManager(Connection connection) {
|
private DeliveryReceiptManager(Connection connection) {
|
||||||
ServiceDiscoveryManager sdm = ServiceDiscoveryManager.getInstanceFor(connection);
|
ServiceDiscoveryManager sdm = ServiceDiscoveryManager.getInstanceFor(connection);
|
||||||
sdm.addFeature(DeliveryReceipt.NAMESPACE);
|
sdm.addFeature(DeliveryReceipt.NAMESPACE);
|
||||||
this.connection = connection;
|
weakRefConnection = new WeakReference<Connection>(connection);
|
||||||
instances.put(connection, this);
|
instances.put(connection, this);
|
||||||
|
|
||||||
// register listener for delivery receipts and requests
|
// register listener for delivery receipts and requests
|
||||||
|
@ -91,6 +92,7 @@ public class DeliveryReceiptManager implements PacketListener {
|
||||||
* @return true if supported
|
* @return true if supported
|
||||||
*/
|
*/
|
||||||
public boolean isSupported(String jid) {
|
public boolean isSupported(String jid) {
|
||||||
|
Connection connection = weakRefConnection.get();
|
||||||
try {
|
try {
|
||||||
DiscoverInfo result =
|
DiscoverInfo result =
|
||||||
ServiceDiscoveryManager.getInstanceFor(connection).discoverInfo(jid);
|
ServiceDiscoveryManager.getInstanceFor(connection).discoverInfo(jid);
|
||||||
|
@ -119,6 +121,7 @@ public class DeliveryReceiptManager implements PacketListener {
|
||||||
DeliveryReceiptRequest drr = (DeliveryReceiptRequest)packet.getExtension(
|
DeliveryReceiptRequest drr = (DeliveryReceiptRequest)packet.getExtension(
|
||||||
DeliveryReceiptRequest.ELEMENT, DeliveryReceipt.NAMESPACE);
|
DeliveryReceiptRequest.ELEMENT, DeliveryReceipt.NAMESPACE);
|
||||||
if (drr != null) {
|
if (drr != null) {
|
||||||
|
Connection connection = weakRefConnection.get();
|
||||||
Message ack = new Message(packet.getFrom(), Message.Type.normal);
|
Message ack = new Message(packet.getFrom(), Message.Type.normal);
|
||||||
ack.addExtension(new DeliveryReceipt(packet.getPacketID()));
|
ack.addExtension(new DeliveryReceipt(packet.getPacketID()));
|
||||||
connection.sendPacket(ack);
|
connection.sendPacket(ack);
|
||||||
|
|
Loading…
Reference in a new issue