diff --git a/src/main/java/software/amazon/awssdk/crt/CrtResource.java b/src/main/java/software/amazon/awssdk/crt/CrtResource.java index a2e8ce037..b711416e5 100644 --- a/src/main/java/software/amazon/awssdk/crt/CrtResource.java +++ b/src/main/java/software/amazon/awssdk/crt/CrtResource.java @@ -124,14 +124,15 @@ public CrtResource() { * @param resource The resource to add a reference to */ public void addReferenceTo(CrtResource resource) { + if (debugNativeObjects) { + Log.log(ResourceLogLevel, Log.LogSubject.JavaCrtResource, + String.format("%s(%d) is adding a reference to %s(%d)", + this.getClass().getCanonicalName(), id, resource.getClass().getCanonicalName(), resource.id)); + } resource.addRef(); synchronized(this) { referencedResources.add(resource); } - - if (debugNativeObjects) { - Log.log(ResourceLogLevel, Log.LogSubject.JavaCrtResource, String.format("Instance of class %s(%d) is adding a reference to instance of class %s(%d)", this.getClass().getCanonicalName(), id, resource.getClass().getCanonicalName(), resource.id)); - } } /** @@ -146,9 +147,13 @@ public void removeReferenceTo(CrtResource resource) { if (debugNativeObjects) { if (removed) { - Log.log(ResourceLogLevel, Log.LogSubject.JavaCrtResource, String.format("Instance of class %s(%d) is removing a reference to instance of class %s(%d)", this.getClass().getCanonicalName(), id, resource.getClass().getCanonicalName(), resource.id)); + Log.log(ResourceLogLevel, Log.LogSubject.JavaCrtResource, + String.format("%s(%d) is removing a reference to %s(%d)", + this.getClass().getCanonicalName(), id, resource.getClass().getCanonicalName(), resource.id)); } else { - Log.log(ResourceLogLevel, Log.LogSubject.JavaCrtResource, String.format("Instance of class %s(%d) erroneously tried to remove a reference to instance of class %s(%d) that it was not referencing", this.getClass().getCanonicalName(), id, resource.getClass().getCanonicalName(), resource.id)); + Log.log(ResourceLogLevel, Log.LogSubject.JavaCrtResource, + String.format("%s(%d) erroneously tried to remove a reference to %s(%d) that it was not referencing", + this.getClass().getCanonicalName(), id, resource.getClass().getCanonicalName(), resource.id)); } } @@ -209,7 +214,8 @@ protected void acquireNativeHandle(long handle) { */ private void release() { if (debugNativeObjects) { - Log.log(ResourceLogLevel, Log.LogSubject.JavaCrtResource, String.format("Releasing class %s(%d)", this.getClass().getCanonicalName(), id)); + Log.log(ResourceLogLevel, Log.LogSubject.JavaCrtResource, + String.format("Releasing class %s(%d)", this.getClass().getCanonicalName(), id)); synchronized(CrtResource.class) { CRT_RESOURCES.remove(id); @@ -237,7 +243,25 @@ public long getNativeHandle() { * Increments the reference count to this resource. */ public void addRef() { - refCount.incrementAndGet(); + int updatedRefs = refCount.incrementAndGet(); + if (debugNativeObjects) { + Log.log(ResourceLogLevel, Log.LogSubject.JavaCrtResource, + String.format("%s(%d) is adding a reference. refCount is now %d", + this.getClass().getCanonicalName(), id, updatedRefs)); + } + } + + /** + * Increments the reference count to this resource with a description. + * @param desc Descrption string of why the reference is being incremented. + */ + public void addRef(String desc) { + int updatedRefs = refCount.incrementAndGet(); + if (debugNativeObjects) { + Log.log(ResourceLogLevel, Log.LogSubject.JavaCrtResource, + String.format("%s(%d) is adding a reference for: (%s). RefCount is now %d", + this.getClass().getCanonicalName(), id, desc, updatedRefs)); + } } /** @@ -274,7 +298,11 @@ public boolean isNull() { @Override public void close() { - decRef(); + decRef("close() called"); + } + + public void close(String desc) { + decRef(desc); } /** @@ -286,12 +314,37 @@ public void decRef(CrtResource decRefInstigator) { int remainingRefs = refCount.decrementAndGet(); if (debugNativeObjects) { - if (decRefInstigator != null) { - Log.log(ResourceLogLevel, Log.LogSubject.JavaCrtResource, String.format( - "DecRef instance of class %s(%d) called by %s(%d). %d remaining refs", this.getClass().getCanonicalName(), id, - decRefInstigator.getClass().getCanonicalName(), decRefInstigator.id, remainingRefs)); + Log.log(ResourceLogLevel, Log.LogSubject.JavaCrtResource, String.format( + "DecRef of %s(%d) called by %s(%d). %d remaining refs", this.getClass().getCanonicalName(), id, + decRefInstigator.getClass().getCanonicalName(), decRefInstigator.id, remainingRefs)); + } + + if (remainingRefs != 0) { + return; + } + + release(); + + if (canReleaseReferencesImmediately()) { + releaseReferences(); + } + } + + /** + * Decrements the reference count to this resource with a description. + * @param desc Descrption string of why the reference is being decremented. + */ + public void decRef(String desc) { + int remainingRefs = refCount.decrementAndGet(); + + if (debugNativeObjects) { + if (desc != null) { + Log.log(ResourceLogLevel, Log.LogSubject.JavaCrtResource, + String.format("DecRef on %s(%d) for: (%s). %d remaining refs", + this.getClass().getCanonicalName(), id, desc, remainingRefs)); } else { - Log.log(ResourceLogLevel, Log.LogSubject.JavaCrtResource, String.format("DecRef instance of class %s(%d) via self.close(). %d remaining refs", + Log.log(ResourceLogLevel, Log.LogSubject.JavaCrtResource, + String.format("Defref on %s(%d). %d remaining refs", this.getClass().getCanonicalName(), id, remainingRefs)); } } @@ -306,11 +359,12 @@ public void decRef(CrtResource decRefInstigator) { releaseReferences(); } } + /** * Decrements the reference count to this resource. */ public void decRef() { - decRef(null); + decRef((String)null); } /** @@ -320,7 +374,9 @@ public void decRef() { */ protected void releaseReferences() { if (debugNativeObjects) { - Log.log(ResourceLogLevel, Log.LogSubject.JavaCrtResource, String.format("Instance of class %s(%d) closing all referenced objects", this.getClass().getCanonicalName(), id)); + Log.log(ResourceLogLevel, Log.LogSubject.JavaCrtResource, + String.format("%s(%d) closing all referenced objects", + this.getClass().getCanonicalName(), id)); } synchronized(this) { diff --git a/src/main/java/software/amazon/awssdk/crt/eventstream/ClientConnectionContinuationHandler.java b/src/main/java/software/amazon/awssdk/crt/eventstream/ClientConnectionContinuationHandler.java index 05598094c..9df218db2 100644 --- a/src/main/java/software/amazon/awssdk/crt/eventstream/ClientConnectionContinuationHandler.java +++ b/src/main/java/software/amazon/awssdk/crt/eventstream/ClientConnectionContinuationHandler.java @@ -67,7 +67,7 @@ public CompletableFuture getContinuationClosedFuture() { @Override public void close() { if (continuation != null) { - continuation.decRef(); + continuation.decRef("close() called"); continuation = null; } } diff --git a/src/main/java/software/amazon/awssdk/crt/eventstream/ClientConnectionHandler.java b/src/main/java/software/amazon/awssdk/crt/eventstream/ClientConnectionHandler.java index f1a4f8623..56689fc4f 100644 --- a/src/main/java/software/amazon/awssdk/crt/eventstream/ClientConnectionHandler.java +++ b/src/main/java/software/amazon/awssdk/crt/eventstream/ClientConnectionHandler.java @@ -93,7 +93,7 @@ public void close() { if (clientConnection.isOpen()) { clientConnection.closeConnection(0); } - clientConnection.decRef(); + clientConnection.decRef("close() called"); clientConnection = null; } } diff --git a/src/main/java/software/amazon/awssdk/crt/eventstream/ServerConnectionContinuationHandler.java b/src/main/java/software/amazon/awssdk/crt/eventstream/ServerConnectionContinuationHandler.java index cd340ee7a..0f5189517 100644 --- a/src/main/java/software/amazon/awssdk/crt/eventstream/ServerConnectionContinuationHandler.java +++ b/src/main/java/software/amazon/awssdk/crt/eventstream/ServerConnectionContinuationHandler.java @@ -68,7 +68,7 @@ public CompletableFuture getContinuationClosedFuture() { @Override public void close() { if (continuation != null) { - continuation.decRef(); + continuation.decRef("close() called"); continuation = null; } } diff --git a/src/main/java/software/amazon/awssdk/crt/eventstream/ServerConnectionHandler.java b/src/main/java/software/amazon/awssdk/crt/eventstream/ServerConnectionHandler.java index f9bb76396..f2b5cf848 100644 --- a/src/main/java/software/amazon/awssdk/crt/eventstream/ServerConnectionHandler.java +++ b/src/main/java/software/amazon/awssdk/crt/eventstream/ServerConnectionHandler.java @@ -76,7 +76,7 @@ public void close() { if (connection.isConnectionOpen()) { connection.closeConnection(0); } - connection.decRef(); + connection.decRef("close() called"); connection = null; } } diff --git a/src/main/java/software/amazon/awssdk/crt/io/ClientBootstrap.java b/src/main/java/software/amazon/awssdk/crt/io/ClientBootstrap.java index 9538f743b..a9bb4d0e3 100644 --- a/src/main/java/software/amazon/awssdk/crt/io/ClientBootstrap.java +++ b/src/main/java/software/amazon/awssdk/crt/io/ClientBootstrap.java @@ -90,7 +90,7 @@ private void onShutdownComplete() { public static void closeStaticDefault() { synchronized (ClientBootstrap.class) { if (staticDefaultClientBootstrap != null) { - staticDefaultClientBootstrap.close(); + staticDefaultClientBootstrap.close("closeStaticDefault"); } staticDefaultClientBootstrap = null; } diff --git a/src/main/java/software/amazon/awssdk/crt/io/EventLoopGroup.java b/src/main/java/software/amazon/awssdk/crt/io/EventLoopGroup.java index 9b8e973ac..3c934d67a 100644 --- a/src/main/java/software/amazon/awssdk/crt/io/EventLoopGroup.java +++ b/src/main/java/software/amazon/awssdk/crt/io/EventLoopGroup.java @@ -95,7 +95,7 @@ public static void setStaticDefaultNumThreads(int numThreads) { public static void closeStaticDefault() { synchronized (EventLoopGroup.class) { if (staticDefaultEventLoopGroup != null) { - staticDefaultEventLoopGroup.close(); + staticDefaultEventLoopGroup.close("closeStaticDefault"); } staticDefaultEventLoopGroup = null; } diff --git a/src/main/java/software/amazon/awssdk/crt/io/HostResolver.java b/src/main/java/software/amazon/awssdk/crt/io/HostResolver.java index 845614739..8f4db4a1f 100644 --- a/src/main/java/software/amazon/awssdk/crt/io/HostResolver.java +++ b/src/main/java/software/amazon/awssdk/crt/io/HostResolver.java @@ -73,7 +73,7 @@ public static void setStaticDefaultMaxEntries(int maxEntries) { public static void closeStaticDefault() { synchronized (HostResolver.class) { if (staticDefaultResolver != null) { - staticDefaultResolver.close(); + staticDefaultResolver.close("closeStaticDefault"); } staticDefaultResolver = null; } diff --git a/src/test/java/software/amazon/awssdk/crt/test/CrtTestFixture.java b/src/test/java/software/amazon/awssdk/crt/test/CrtTestFixture.java index d12e8a85d..1194a64ac 100644 --- a/src/test/java/software/amazon/awssdk/crt/test/CrtTestFixture.java +++ b/src/test/java/software/amazon/awssdk/crt/test/CrtTestFixture.java @@ -23,6 +23,9 @@ import org.junit.BeforeClass; import org.junit.After; import org.junit.Assume; +import org.junit.Rule; +import org.junit.rules.TestName; + import java.util.Optional; @@ -30,6 +33,9 @@ public class CrtTestFixture { private CrtTestContext context; + @Rule + public TestName testName = new TestName(); + public final CrtTestContext getContext() { return context; } @@ -230,6 +236,7 @@ public static void setupOnce() { /* The setup function will be run before every test */ @Before public void setup() { + System.out.println("[TEST START] " + testName.getMethodName()); Log.log(Log.LogLevel.Debug, LogSubject.JavaCrtGeneral, "CrtTestFixture setup begin"); // TODO this CrtTestContext should be removed as we are using System Properties @@ -258,6 +265,7 @@ public void tearDown() { } } Log.log(Log.LogLevel.Debug, LogSubject.JavaCrtGeneral, "CrtTestFixture tearDown end"); + System.out.println("[TEST END] " + testName.getMethodName()); } protected TlsContext createTlsContextOptions(byte[] trustStore) {