From f9559f17e0604a1b2db048bca35b700670639944 Mon Sep 17 00:00:00 2001 From: cpovirk Date: Thu, 12 Dec 2024 07:34:55 -0800 Subject: [PATCH] Release `testMyServerExampleWithCleaner` publicly. (followup cl/705490132) The method requires JDK 9+ to build, but our Maven build [always builds with JDK 23](https://github.com/google/guava/issues/6549#issuecomment-2539090735). It also requires JDK 9+ to _run_, so I've added code to skip running the test under older versions. Much of my goal here is to shake out any ways that we might cause problems if we begin conditionally using Java 9+ APIs more widely, such as [for `VarHandle`](https://github.com/google/guava/issues/6806#issuecomment-2515993574). RELNOTES=n/a PiperOrigin-RevId: 705498400 --- .../base/FinalizableReferenceQueueTest.java | 53 +++++++++++++++++++ .../base/FinalizableReferenceQueueTest.java | 53 +++++++++++++++++++ 2 files changed, 106 insertions(+) diff --git a/android/guava-tests/test/com/google/common/base/FinalizableReferenceQueueTest.java b/android/guava-tests/test/com/google/common/base/FinalizableReferenceQueueTest.java index db1288c4dca9..534728db0942 100644 --- a/android/guava-tests/test/com/google/common/base/FinalizableReferenceQueueTest.java +++ b/android/guava-tests/test/com/google/common/base/FinalizableReferenceQueueTest.java @@ -25,6 +25,8 @@ import java.io.Closeable; import java.io.IOException; import java.io.UncheckedIOException; +import java.lang.ref.Cleaner; +import java.lang.ref.Cleaner.Cleanable; import java.lang.ref.Reference; import java.lang.ref.ReferenceQueue; import java.lang.ref.WeakReference; @@ -220,4 +222,55 @@ public void testMyServerExampleWithFrq() throws Exception { GcFinalization.awaitDone(finalizeReferentRan::get); assertThat(serverSocket.isClosed()).isTrue(); } + + @SuppressWarnings("Java8ApiChecker") + static class MyServerExampleWithCleaner implements AutoCloseable { + private static final Cleaner cleaner = Cleaner.create(); + + private static Runnable closeServerSocketRunnable( + ServerSocket serverSocket, AtomicBoolean cleanerRan) { + return () -> { + cleanerRan.set(true); + try { + serverSocket.close(); + } catch (IOException e) { + throw new UncheckedIOException(e); + } + }; + } + + private final ServerSocket serverSocket; + private final Cleanable cleanable; + + MyServerExampleWithCleaner(AtomicBoolean cleanerRan) throws IOException { + this.serverSocket = new ServerSocket(0); + this.cleanable = cleaner.register(this, closeServerSocketRunnable(serverSocket, cleanerRan)); + } + + @Override + public void close() { + cleanable.clean(); + } + } + + @SuppressWarnings("Java8ApiChecker") + private ServerSocket makeMyServerExampleWithCleaner(AtomicBoolean cleanerRan) throws IOException { + MyServerExampleWithCleaner myServer = new MyServerExampleWithCleaner(cleanerRan); + assertThat(myServer.serverSocket.isClosed()).isFalse(); + return myServer.serverSocket; + } + + @SuppressWarnings("Java8ApiChecker") + @Test + public void testMyServerExampleWithCleaner() throws Exception { + try { + Class.forName("java.lang.ref.Cleaner"); + } catch (ClassNotFoundException beforeJava9) { + return; + } + AtomicBoolean cleanerRan = new AtomicBoolean(false); + ServerSocket serverSocket = makeMyServerExampleWithCleaner(cleanerRan); + GcFinalization.awaitDone(cleanerRan::get); + assertThat(serverSocket.isClosed()).isTrue(); + } } diff --git a/guava-tests/test/com/google/common/base/FinalizableReferenceQueueTest.java b/guava-tests/test/com/google/common/base/FinalizableReferenceQueueTest.java index db1288c4dca9..534728db0942 100644 --- a/guava-tests/test/com/google/common/base/FinalizableReferenceQueueTest.java +++ b/guava-tests/test/com/google/common/base/FinalizableReferenceQueueTest.java @@ -25,6 +25,8 @@ import java.io.Closeable; import java.io.IOException; import java.io.UncheckedIOException; +import java.lang.ref.Cleaner; +import java.lang.ref.Cleaner.Cleanable; import java.lang.ref.Reference; import java.lang.ref.ReferenceQueue; import java.lang.ref.WeakReference; @@ -220,4 +222,55 @@ public void testMyServerExampleWithFrq() throws Exception { GcFinalization.awaitDone(finalizeReferentRan::get); assertThat(serverSocket.isClosed()).isTrue(); } + + @SuppressWarnings("Java8ApiChecker") + static class MyServerExampleWithCleaner implements AutoCloseable { + private static final Cleaner cleaner = Cleaner.create(); + + private static Runnable closeServerSocketRunnable( + ServerSocket serverSocket, AtomicBoolean cleanerRan) { + return () -> { + cleanerRan.set(true); + try { + serverSocket.close(); + } catch (IOException e) { + throw new UncheckedIOException(e); + } + }; + } + + private final ServerSocket serverSocket; + private final Cleanable cleanable; + + MyServerExampleWithCleaner(AtomicBoolean cleanerRan) throws IOException { + this.serverSocket = new ServerSocket(0); + this.cleanable = cleaner.register(this, closeServerSocketRunnable(serverSocket, cleanerRan)); + } + + @Override + public void close() { + cleanable.clean(); + } + } + + @SuppressWarnings("Java8ApiChecker") + private ServerSocket makeMyServerExampleWithCleaner(AtomicBoolean cleanerRan) throws IOException { + MyServerExampleWithCleaner myServer = new MyServerExampleWithCleaner(cleanerRan); + assertThat(myServer.serverSocket.isClosed()).isFalse(); + return myServer.serverSocket; + } + + @SuppressWarnings("Java8ApiChecker") + @Test + public void testMyServerExampleWithCleaner() throws Exception { + try { + Class.forName("java.lang.ref.Cleaner"); + } catch (ClassNotFoundException beforeJava9) { + return; + } + AtomicBoolean cleanerRan = new AtomicBoolean(false); + ServerSocket serverSocket = makeMyServerExampleWithCleaner(cleanerRan); + GcFinalization.awaitDone(cleanerRan::get); + assertThat(serverSocket.isClosed()).isTrue(); + } }