summaryrefslogtreecommitdiff
path: root/java/src
diff options
context:
space:
mode:
authorJose <jose@zeroc.com>2008-12-18 14:32:27 +0100
committerJose <jose@zeroc.com>2008-12-18 14:32:27 +0100
commit57a0a4333fbb0b41cd7423b37b59534455a3173b (patch)
tree174b28cf580405b213ae4da8fd96b2ca509bd9aa /java/src
parentMerge branch 'R3_3_branch'; commit 'origin/R3_3_branch' into R3_3_branch (diff)
downloadice-57a0a4333fbb0b41cd7423b37b59534455a3173b.tar.bz2
ice-57a0a4333fbb0b41cd7423b37b59534455a3173b.tar.xz
ice-57a0a4333fbb0b41cd7423b37b59534455a3173b.zip
Revert "Remove Java finalizers code"
This reverts commit 94e1da6dc82a8ed38ee7a5691d691d375aaa28cb.
Diffstat (limited to 'java/src')
-rw-r--r--java/src/Freeze/ConnectionI.java31
-rw-r--r--java/src/Freeze/EvictorI.java11
-rw-r--r--java/src/Freeze/Map.java76
-rw-r--r--java/src/Freeze/TransactionalEvictorContext.java11
-rw-r--r--java/src/Ice/CommunicatorI.java17
-rw-r--r--java/src/Ice/ConnectionI.java15
-rw-r--r--java/src/Ice/ObjectAdapterI.java29
-rw-r--r--java/src/IceInternal/ConnectionMonitor.java10
-rw-r--r--java/src/IceInternal/IncomingConnectionFactory.java11
-rw-r--r--java/src/IceInternal/Instance.java25
-rw-r--r--java/src/IceInternal/ObjectAdapterFactory.java12
-rw-r--r--java/src/IceInternal/OutgoingAsyncMessageCallback.java10
-rw-r--r--java/src/IceInternal/OutgoingConnectionFactory.java13
-rw-r--r--java/src/IceInternal/PropertyNames.java1
-rw-r--r--java/src/IceInternal/SelectorThread.java7
-rw-r--r--java/src/IceInternal/ServantManager.java14
-rw-r--r--java/src/IceInternal/TcpAcceptor.java9
-rw-r--r--java/src/IceInternal/TcpConnector.java7
-rw-r--r--java/src/IceInternal/TcpTransceiver.java9
-rw-r--r--java/src/IceInternal/ThreadPool.java7
-rw-r--r--java/src/IceInternal/Timer.java9
-rw-r--r--java/src/IceInternal/UdpTransceiver.java9
-rw-r--r--java/src/IceSSL/AcceptorI.java9
-rw-r--r--java/src/IceSSL/ConnectorI.java7
-rw-r--r--java/src/IceSSL/TransceiverI.java9
-rw-r--r--java/src/IceUtilInternal/Assert.java45
26 files changed, 392 insertions, 21 deletions
diff --git a/java/src/Freeze/ConnectionI.java b/java/src/Freeze/ConnectionI.java
index 3913ec614a6..45053c39556 100644
--- a/java/src/Freeze/ConnectionI.java
+++ b/java/src/Freeze/ConnectionI.java
@@ -61,6 +61,12 @@ class ConnectionI implements Connection
}
+ public void
+ close()
+ {
+ close(false);
+ }
+
public Ice.Communicator
getCommunicator()
{
@@ -73,11 +79,23 @@ class ConnectionI implements Connection
return _envName;
}
- public void
- close()
+ protected void
+ finalize()
+ {
+ close(true);
+ }
+
+ void
+ close(boolean finalizing)
{
if(_transaction != null)
{
+ if(finalizing)
+ {
+ _communicator.getLogger().warning
+ ("Finalizing Connection on DbEnv \"" + _envName + "\" with active transaction");
+ }
+
try
{
_transaction.rollback();
@@ -96,7 +114,7 @@ class ConnectionI implements Connection
java.util.Iterator p = _mapList.iterator();
while(p.hasNext())
{
- ((Map) p.next()).close();
+ ((Map) p.next()).close(finalizing);
}
}
@@ -124,6 +142,7 @@ class ConnectionI implements Connection
Ice.Properties properties = _communicator.getProperties();
_deadlockWarning = properties.getPropertyAsInt("Freeze.Warn.Deadlocks") > 0;
+ _closeInFinalizeWarning = properties.getPropertyAsIntWithDefault("Freeze.Warn.CloseInFinalize", 1) > 0;
}
ConnectionI(Ice.Communicator communicator, String envName, com.sleepycat.db.Environment dbEnv)
@@ -216,6 +235,11 @@ class ConnectionI implements Connection
return _deadlockWarning;
}
+ final boolean
+ closeInFinalizeWarning()
+ {
+ return _closeInFinalizeWarning;
+ }
private String errorPrefix()
{
@@ -231,4 +255,5 @@ class ConnectionI implements Connection
private int _trace;
private int _txTrace;
private boolean _deadlockWarning;
+ private boolean _closeInFinalizeWarning;
}
diff --git a/java/src/Freeze/EvictorI.java b/java/src/Freeze/EvictorI.java
index 576760e7062..51b62e314dc 100644
--- a/java/src/Freeze/EvictorI.java
+++ b/java/src/Freeze/EvictorI.java
@@ -273,6 +273,17 @@ abstract class EvictorI implements Evictor
abstract protected void evict();
+
+ synchronized protected void
+ finalize()
+ {
+ if(!_deactivateController.deactivated())
+ {
+ _communicator.getLogger().warning("Freeze evictor " + toString() + " has not been deactivated");
+ deactivate("");
+ }
+ }
+
protected void
closeDbEnv()
{
diff --git a/java/src/Freeze/Map.java b/java/src/Freeze/Map.java
index 6b9ce2ab8b7..b2ad20012c0 100644
--- a/java/src/Freeze/Map.java
+++ b/java/src/Freeze/Map.java
@@ -281,9 +281,15 @@ public abstract class Map extends java.util.AbstractMap
}
public void
+ close()
+ {
+ close(false);
+ }
+
+ public void
closeDb()
{
- close();
+ close(false);
_connection.dbEnv().removeSharedMapDb(_dbName);
}
@@ -837,7 +843,7 @@ public abstract class Map extends java.util.AbstractMap
public void
closeAllIterators()
{
- closeAllIteratorsExcept(null);
+ closeAllIteratorsExcept(null, false);
}
@@ -957,7 +963,7 @@ public abstract class Map extends java.util.AbstractMap
void
- closeAllIteratorsExcept(Object except)
+ closeAllIteratorsExcept(Object except, boolean finalizing)
{
synchronized(_iteratorList)
{
@@ -968,29 +974,38 @@ public abstract class Map extends java.util.AbstractMap
Object obj = p.next();
if(obj != except)
{
- ((EntryIteratorImpl)obj).close();
+ ((EntryIteratorImpl)obj).close(finalizing);
}
}
}
}
+ protected void
+ finalize()
+ {
+ close(true);
+ }
+
//
// The synchronization is only needed when finalizing is true
//
- public void
- close()
+ void
+ close(boolean finalizing)
{
- if(_db != null)
+ synchronized(_connection)
{
- try
- {
- closeAllIteratorsExcept(null);
- }
- finally
+ if(_db != null)
{
- _db = null;
- _connection.unregisterMap(_token);
- _token = null;
+ try
+ {
+ closeAllIteratorsExcept(null, finalizing);
+ }
+ finally
+ {
+ _db = null;
+ _connection.unregisterMap(_token);
+ _token = null;
+ }
}
}
}
@@ -1920,7 +1935,7 @@ public abstract class Map extends java.util.AbstractMap
{
if(_txn != null)
{
- closeAllIteratorsExcept(this);
+ closeAllIteratorsExcept(this, false);
}
//
@@ -2019,9 +2034,30 @@ public abstract class Map extends java.util.AbstractMap
}
}
+ //
+ // Extra operations.
+ //
public void
close()
{
+ close(false);
+ }
+
+ //
+ // The synchronized is needed because this method can be called
+ // concurrently by Connection, Map and Map.EntryIterator finalizers.
+ //
+ synchronized void
+ close(boolean finalizing)
+ {
+ if(finalizing && (_cursor != null || _txn != null) && _connection.closeInFinalizeWarning())
+ {
+ _connection.communicator().getLogger().warning(
+ "finalize() closing a live iterator on Map \"" + _db.dbName() + "\"; the application " +
+ "should have closed it earlier by calling Map.EntryIterator.close(), " +
+ "Map.closeAllIterators(), Map.close(), Connection.close(), or (if also " +
+ "leaking a transaction) Transaction.commit() or Transaction.rollback()");
+ }
if(_iteratorListToken != null)
{
@@ -2102,6 +2138,12 @@ public abstract class Map extends java.util.AbstractMap
close();
}
+ protected void
+ finalize()
+ {
+ close(true);
+ }
+
void
setValue(Map.Entry entry, Object value)
{
@@ -2113,7 +2155,7 @@ public abstract class Map extends java.util.AbstractMap
if(_txn != null)
{
- closeAllIteratorsExcept(this);
+ closeAllIteratorsExcept(this, false);
}
//
diff --git a/java/src/Freeze/TransactionalEvictorContext.java b/java/src/Freeze/TransactionalEvictorContext.java
index 50fe354ef7c..2de368abeb0 100644
--- a/java/src/Freeze/TransactionalEvictorContext.java
+++ b/java/src/Freeze/TransactionalEvictorContext.java
@@ -351,6 +351,17 @@ class TransactionalEvictorContext implements Ice.DispatchInterceptorAsyncCallbac
}
return null;
}
+
+
+ protected void
+ finalize()
+ {
+ if(_tx != null)
+ {
+ _tx.getConnectionI().communicator().getLogger().warning
+ ("Finalizing incomplete TransactionalEvictorContext on DbEnv '" + _tx.getConnectionI().dbEnv().getEnvName() + "'");
+ }
+ }
private ServantHolder
findServantHolder(Ice.Identity ident, ObjectStore store)
diff --git a/java/src/Ice/CommunicatorI.java b/java/src/Ice/CommunicatorI.java
index 73a77567aa6..8562f0fd7ac 100644
--- a/java/src/Ice/CommunicatorI.java
+++ b/java/src/Ice/CommunicatorI.java
@@ -196,6 +196,23 @@ public final class CommunicatorI implements Communicator
_instance = new IceInternal.Instance(this, initData);
}
+ /**
+ * For compatibility with C#, we do not invoke methods on other objects
+ * from within a finalizer.
+ *
+ protected synchronized void
+ finalize()
+ throws Throwable
+ {
+ if(!_instance.destroyed())
+ {
+ _instance.logger().warning("Ice::Communicator::destroy() has not been called");
+ }
+
+ super.finalize();
+ }
+ */
+
//
// Certain initialization tasks need to be completed after the
// constructor.
diff --git a/java/src/Ice/ConnectionI.java b/java/src/Ice/ConnectionI.java
index 170a1030658..eb9b2a88a76 100644
--- a/java/src/Ice/ConnectionI.java
+++ b/java/src/Ice/ConnectionI.java
@@ -1285,6 +1285,21 @@ public final class ConnectionI extends IceInternal.EventHandler implements Conne
}
}
+ protected synchronized void
+ finalize()
+ throws Throwable
+ {
+ IceUtilInternal.Assert.FinalizerAssert(_startCallback == null);
+ IceUtilInternal.Assert.FinalizerAssert(_state == StateClosed);
+ IceUtilInternal.Assert.FinalizerAssert(_transceiver == null);
+ IceUtilInternal.Assert.FinalizerAssert(_dispatchCount == 0);
+ IceUtilInternal.Assert.FinalizerAssert(_sendStreams.isEmpty());
+ IceUtilInternal.Assert.FinalizerAssert(_requests.isEmpty());
+ IceUtilInternal.Assert.FinalizerAssert(_asyncRequests.isEmpty());
+
+ super.finalize();
+ }
+
private static final int StateNotInitialized = 0;
private static final int StateNotValidated = 1;
private static final int StateActive = 2;
diff --git a/java/src/Ice/ObjectAdapterI.java b/java/src/Ice/ObjectAdapterI.java
index 61af2b359d6..5c6d7755cf1 100644
--- a/java/src/Ice/ObjectAdapterI.java
+++ b/java/src/Ice/ObjectAdapterI.java
@@ -355,6 +355,9 @@ public final class ObjectAdapterI implements ObjectAdapter
// We're done, now we can throw away all incoming connection
// factories.
//
+ // For compatibility with C#, we set _incomingConnectionFactories
+ // to null so that the finalizer does not invoke methods on objects.
+ //
_incomingConnectionFactories = null;
//
@@ -937,6 +940,32 @@ public final class ObjectAdapterI implements ObjectAdapter
}
}
+ protected synchronized void
+ finalize()
+ throws Throwable
+ {
+ if(!_deactivated)
+ {
+ _instance.initializationData().logger.warning("object adapter `" + getName() +
+ "' has not been deactivated");
+ }
+ else if(!_destroyed)
+ {
+ _instance.initializationData().logger.warning("object adapter `" + getName() + "' has not been destroyed");
+ }
+ else
+ {
+ IceUtilInternal.Assert.FinalizerAssert(_threadPool == null);
+ //IceUtilInternal.Assert.FinalizerAssert(_servantManager == null); // Not cleared, it needs to be immutable.
+ IceUtilInternal.Assert.FinalizerAssert(_communicator == null);
+ IceUtilInternal.Assert.FinalizerAssert(_incomingConnectionFactories == null);
+ IceUtilInternal.Assert.FinalizerAssert(_directCount == 0);
+ IceUtilInternal.Assert.FinalizerAssert(!_waitForActivate);
+ }
+
+ super.finalize();
+ }
+
private ObjectPrx
newProxy(Identity ident, String facet)
{
diff --git a/java/src/IceInternal/ConnectionMonitor.java b/java/src/IceInternal/ConnectionMonitor.java
index de7652e0069..6483c5242af 100644
--- a/java/src/IceInternal/ConnectionMonitor.java
+++ b/java/src/IceInternal/ConnectionMonitor.java
@@ -48,6 +48,16 @@ public final class ConnectionMonitor implements IceInternal.TimerTask
_instance.timer().scheduleRepeated(this, interval * 1000);
}
+ protected synchronized void
+ finalize()
+ throws Throwable
+ {
+ IceUtilInternal.Assert.FinalizerAssert(_instance == null);
+ IceUtilInternal.Assert.FinalizerAssert(_connections == null);
+
+ super.finalize();
+ }
+
public void
runTimerTask()
{
diff --git a/java/src/IceInternal/IncomingConnectionFactory.java b/java/src/IceInternal/IncomingConnectionFactory.java
index eae8c27151b..2a6b1263e2a 100644
--- a/java/src/IceInternal/IncomingConnectionFactory.java
+++ b/java/src/IceInternal/IncomingConnectionFactory.java
@@ -491,6 +491,17 @@ public final class IncomingConnectionFactory extends EventHandler implements Ice
}
}
+ protected synchronized void
+ finalize()
+ throws Throwable
+ {
+ IceUtilInternal.Assert.FinalizerAssert(_state == StateClosed);
+ IceUtilInternal.Assert.FinalizerAssert(_acceptor == null);
+ IceUtilInternal.Assert.FinalizerAssert(_connections == null);
+
+ super.finalize();
+ }
+
private static final int StateActive = 0;
private static final int StateHolding = 1;
private static final int StateClosed = 2;
diff --git a/java/src/IceInternal/Instance.java b/java/src/IceInternal/Instance.java
index 2cfd7ee8850..b4606bd206f 100644
--- a/java/src/IceInternal/Instance.java
+++ b/java/src/IceInternal/Instance.java
@@ -746,6 +746,31 @@ public final class Instance
}
}
+ protected synchronized void
+ finalize()
+ throws Throwable
+ {
+ IceUtilInternal.Assert.FinalizerAssert(_state == StateDestroyed);
+ IceUtilInternal.Assert.FinalizerAssert(_referenceFactory == null);
+ IceUtilInternal.Assert.FinalizerAssert(_proxyFactory == null);
+ IceUtilInternal.Assert.FinalizerAssert(_outgoingConnectionFactory == null);
+ IceUtilInternal.Assert.FinalizerAssert(_connectionMonitor == null);
+ IceUtilInternal.Assert.FinalizerAssert(_servantFactoryManager == null);
+ IceUtilInternal.Assert.FinalizerAssert(_objectAdapterFactory == null);
+ IceUtilInternal.Assert.FinalizerAssert(_clientThreadPool == null);
+ IceUtilInternal.Assert.FinalizerAssert(_serverThreadPool == null);
+ IceUtilInternal.Assert.FinalizerAssert(_selectorThread == null);
+ IceUtilInternal.Assert.FinalizerAssert(_endpointHostResolver == null);
+ IceUtilInternal.Assert.FinalizerAssert(_timer == null);
+ IceUtilInternal.Assert.FinalizerAssert(_routerManager == null);
+ IceUtilInternal.Assert.FinalizerAssert(_locatorManager == null);
+ IceUtilInternal.Assert.FinalizerAssert(_endpointFactoryManager == null);
+ IceUtilInternal.Assert.FinalizerAssert(_pluginManager == null);
+ IceUtilInternal.Assert.FinalizerAssert(_retryQueue == null);
+
+ super.finalize();
+ }
+
public void
finishSetup(Ice.StringSeqHolder args)
{
diff --git a/java/src/IceInternal/ObjectAdapterFactory.java b/java/src/IceInternal/ObjectAdapterFactory.java
index e6a1790324a..9dd4779930f 100644
--- a/java/src/IceInternal/ObjectAdapterFactory.java
+++ b/java/src/IceInternal/ObjectAdapterFactory.java
@@ -262,6 +262,18 @@ public final class ObjectAdapterFactory
_waitForShutdown = false;
}
+ protected synchronized void
+ finalize()
+ throws Throwable
+ {
+ IceUtilInternal.Assert.FinalizerAssert(_instance == null);
+ IceUtilInternal.Assert.FinalizerAssert(_communicator == null);
+ IceUtilInternal.Assert.FinalizerAssert(_adapters == null);
+ IceUtilInternal.Assert.FinalizerAssert(!_waitForShutdown);
+
+ super.finalize();
+ }
+
private Instance _instance;
private Ice.Communicator _communicator;
private java.util.Map<String, Ice.ObjectAdapterI> _adapters = new java.util.HashMap<String, Ice.ObjectAdapterI>();
diff --git a/java/src/IceInternal/OutgoingAsyncMessageCallback.java b/java/src/IceInternal/OutgoingAsyncMessageCallback.java
index 6e8cb9d807c..a0d21e7ad90 100644
--- a/java/src/IceInternal/OutgoingAsyncMessageCallback.java
+++ b/java/src/IceInternal/OutgoingAsyncMessageCallback.java
@@ -51,6 +51,14 @@ abstract public class OutgoingAsyncMessageCallback
}
}
+ protected synchronized void
+ finalize()
+ throws Throwable
+ {
+ assert(__os == null);
+ assert(__is == null);
+ }
+
protected void
__acquireCallback(Ice.ObjectPrx proxy)
{
@@ -74,7 +82,7 @@ abstract public class OutgoingAsyncMessageCallback
assert(__is == null);
__is = new BasicStream(ref.getInstance());
assert(__os == null);
- __os = new BasicStream(ref.getInstance());
+ __os = new BasicStream(ref.getInstance());
}
}
diff --git a/java/src/IceInternal/OutgoingConnectionFactory.java b/java/src/IceInternal/OutgoingConnectionFactory.java
index e6d8e6cad02..58177812f6d 100644
--- a/java/src/IceInternal/OutgoingConnectionFactory.java
+++ b/java/src/IceInternal/OutgoingConnectionFactory.java
@@ -417,6 +417,19 @@ public final class OutgoingConnectionFactory
_destroyed = false;
}
+ protected synchronized void
+ finalize()
+ throws Throwable
+ {
+ IceUtilInternal.Assert.FinalizerAssert(_destroyed);
+ IceUtilInternal.Assert.FinalizerAssert(_connections == null);
+ IceUtilInternal.Assert.FinalizerAssert(_connectionsByEndpoint == null);
+ IceUtilInternal.Assert.FinalizerAssert(_pendingConnectCount == 0);
+ IceUtilInternal.Assert.FinalizerAssert(_pending.isEmpty());
+
+ super.finalize();
+ }
+
private java.util.List<EndpointI>
applyOverrides(EndpointI[] endpts)
{
diff --git a/java/src/IceInternal/PropertyNames.java b/java/src/IceInternal/PropertyNames.java
index 6dc0ec9fdd0..439d3a099cc 100644
--- a/java/src/IceInternal/PropertyNames.java
+++ b/java/src/IceInternal/PropertyNames.java
@@ -550,6 +550,7 @@ public final class PropertyNames
new Property("Freeze\\.Trace\\.Evictor", false, null),
new Property("Freeze\\.Trace\\.Map", false, null),
new Property("Freeze\\.Trace\\.Transaction", false, null),
+ new Property("Freeze\\.Warn\\.CloseInFinalize", false, null),
new Property("Freeze\\.Warn\\.Deadlocks", false, null),
new Property("Freeze\\.Warn\\.Rollback", false, null),
null
diff --git a/java/src/IceInternal/SelectorThread.java b/java/src/IceInternal/SelectorThread.java
index 6103a9e45a6..e34cc480ddc 100644
--- a/java/src/IceInternal/SelectorThread.java
+++ b/java/src/IceInternal/SelectorThread.java
@@ -40,6 +40,13 @@ public class SelectorThread
_timer = _instance.timer();
}
+ protected synchronized void
+ finalize()
+ throws Throwable
+ {
+ IceUtilInternal.Assert.FinalizerAssert(_destroyed);
+ }
+
public synchronized void
destroy()
{
diff --git a/java/src/IceInternal/ServantManager.java b/java/src/IceInternal/ServantManager.java
index 931b383b7fe..8e4dcc1374a 100644
--- a/java/src/IceInternal/ServantManager.java
+++ b/java/src/IceInternal/ServantManager.java
@@ -199,6 +199,20 @@ public final class ServantManager
_adapterName = adapterName;
}
+ protected void
+ finalize()
+ throws Throwable
+ {
+ //
+ // Don't check whether destroy() has been called. It might have
+ // not been called if the associated object adapter was not
+ // properly deactivated.
+ //
+ //IceUtilInternal.Assert.FinalizerAssert(_instance == null);
+
+ super.finalize();
+ }
+
//
// Only for use by Ice.ObjectAdapterI.
//
diff --git a/java/src/IceInternal/TcpAcceptor.java b/java/src/IceInternal/TcpAcceptor.java
index bdbf6188ab2..e09bf7c760d 100644
--- a/java/src/IceInternal/TcpAcceptor.java
+++ b/java/src/IceInternal/TcpAcceptor.java
@@ -115,6 +115,15 @@ class TcpAcceptor implements Acceptor
}
}
+ protected synchronized void
+ finalize()
+ throws Throwable
+ {
+ IceUtilInternal.Assert.FinalizerAssert(_fd == null);
+
+ super.finalize();
+ }
+
private Instance _instance;
private TraceLevels _traceLevels;
private Ice.Logger _logger;
diff --git a/java/src/IceInternal/TcpConnector.java b/java/src/IceInternal/TcpConnector.java
index 3c7a76f960c..99a80dff1db 100644
--- a/java/src/IceInternal/TcpConnector.java
+++ b/java/src/IceInternal/TcpConnector.java
@@ -143,6 +143,13 @@ final class TcpConnector implements Connector, java.lang.Comparable
}
return Network.compareAddress(_addr, p._addr);
+ }
+
+ protected synchronized void
+ finalize()
+ throws Throwable
+ {
+ super.finalize();
}
private Instance _instance;
diff --git a/java/src/IceInternal/TcpTransceiver.java b/java/src/IceInternal/TcpTransceiver.java
index ac7715b9b15..548f2c3a94b 100644
--- a/java/src/IceInternal/TcpTransceiver.java
+++ b/java/src/IceInternal/TcpTransceiver.java
@@ -263,6 +263,15 @@ final class TcpTransceiver implements Transceiver
}
}
+ protected synchronized void
+ finalize()
+ throws Throwable
+ {
+ IceUtilInternal.Assert.FinalizerAssert(_fd == null);
+
+ super.finalize();
+ }
+
private java.nio.channels.SocketChannel _fd;
private TraceLevels _traceLevels;
private Ice.Logger _logger;
diff --git a/java/src/IceInternal/ThreadPool.java b/java/src/IceInternal/ThreadPool.java
index 3898fe0a0b6..6f19615ecf0 100644
--- a/java/src/IceInternal/ThreadPool.java
+++ b/java/src/IceInternal/ThreadPool.java
@@ -107,6 +107,13 @@ public final class ThreadPool
}
}
+ protected synchronized void
+ finalize()
+ throws Throwable
+ {
+ IceUtilInternal.Assert.FinalizerAssert(_destroyed);
+ }
+
public synchronized void
destroy()
{
diff --git a/java/src/IceInternal/Timer.java b/java/src/IceInternal/Timer.java
index 92d3f4c2300..b4805e22b6b 100644
--- a/java/src/IceInternal/Timer.java
+++ b/java/src/IceInternal/Timer.java
@@ -128,6 +128,15 @@ public final class Timer extends Thread
start();
}
+ protected synchronized void
+ finalize()
+ throws Throwable
+ {
+ IceUtilInternal.Assert.FinalizerAssert(_instance == null);
+
+ super.finalize();
+ }
+
public void
run()
{
diff --git a/java/src/IceInternal/UdpTransceiver.java b/java/src/IceInternal/UdpTransceiver.java
index 85774a23607..84aef93ffb8 100644
--- a/java/src/IceInternal/UdpTransceiver.java
+++ b/java/src/IceInternal/UdpTransceiver.java
@@ -517,6 +517,15 @@ final class UdpTransceiver implements Transceiver
{
}
+ protected synchronized void
+ finalize()
+ throws Throwable
+ {
+ IceUtilInternal.Assert.FinalizerAssert(_fd == null);
+
+ super.finalize();
+ }
+
private TraceLevels _traceLevels;
private Ice.Logger _logger;
private Ice.Stats _stats;
diff --git a/java/src/IceSSL/AcceptorI.java b/java/src/IceSSL/AcceptorI.java
index 2e409429a31..29984ec9d6f 100644
--- a/java/src/IceSSL/AcceptorI.java
+++ b/java/src/IceSSL/AcceptorI.java
@@ -137,6 +137,15 @@ final class AcceptorI implements IceInternal.Acceptor
}
}
+ protected synchronized void
+ finalize()
+ throws Throwable
+ {
+ IceUtilInternal.Assert.FinalizerAssert(_fd == null);
+
+ super.finalize();
+ }
+
private Instance _instance;
private String _adapterName;
private Ice.Logger _logger;
diff --git a/java/src/IceSSL/ConnectorI.java b/java/src/IceSSL/ConnectorI.java
index e96a781f33a..370237563e8 100644
--- a/java/src/IceSSL/ConnectorI.java
+++ b/java/src/IceSSL/ConnectorI.java
@@ -156,6 +156,13 @@ final class ConnectorI implements IceInternal.Connector, java.lang.Comparable
return IceInternal.Network.compareAddress(_addr, p._addr);
}
+ protected synchronized void
+ finalize()
+ throws Throwable
+ {
+ super.finalize();
+ }
+
private Instance _instance;
private Ice.Logger _logger;
private String _host;
diff --git a/java/src/IceSSL/TransceiverI.java b/java/src/IceSSL/TransceiverI.java
index eb95bff146a..3ef8a5c63d7 100644
--- a/java/src/IceSSL/TransceiverI.java
+++ b/java/src/IceSSL/TransceiverI.java
@@ -336,6 +336,15 @@ final class TransceiverI implements IceInternal.Transceiver
_netOutput = ByteBuffer.allocateDirect(engine.getSession().getPacketBufferSize() * 2);
}
+ protected void
+ finalize()
+ throws Throwable
+ {
+ IceUtilInternal.Assert.FinalizerAssert(_fd == null);
+
+ super.finalize();
+ }
+
private IceInternal.SocketStatus
handshakeNonBlocking()
{
diff --git a/java/src/IceUtilInternal/Assert.java b/java/src/IceUtilInternal/Assert.java
new file mode 100644
index 00000000000..314f20d8200
--- /dev/null
+++ b/java/src/IceUtilInternal/Assert.java
@@ -0,0 +1,45 @@
+// **********************************************************************
+//
+// Copyright (c) 2003-2008 ZeroC, Inc. All rights reserved.
+//
+// This copy of Ice is licensed to you under the terms described in the
+// ICE_LICENSE file included in this distribution.
+//
+// **********************************************************************
+
+package IceUtilInternal;
+
+public final class Assert
+{
+ //
+ // The JVM ignores exceptions raised in finalizers, therefore finalizers
+ // that use assertions should call this method instead of assert().
+ //
+ public static void
+ FinalizerAssert(boolean b)
+ {
+ if(!b)
+ {
+ //
+ // Create a Throwable to obtain the stack trace.
+ //
+ Throwable t = new Throwable();
+ StackTraceElement[] trace = t.getStackTrace();
+ if(trace.length > 1)
+ {
+ //
+ // Skip the first frame, which represents this method.
+ //
+ System.err.println("Assertion failure:");
+ for(int i = 1; i < trace.length; ++i)
+ {
+ System.err.println("\tat " + trace[i]);
+ }
+ }
+ else
+ {
+ System.err.println("Assertion failure (no stack trace information)");
+ }
+ }
+ }
+}