You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@commons.apache.org by gg...@apache.org on 2021/09/19 16:16:40 UTC

[commons-io] 01/02: Method that allocates should release resources.

This is an automated email from the ASF dual-hosted git repository.

ggregory pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/commons-io.git

commit 69e3b819a154793128ec7c0336d33623f6cc8a21
Author: Gary Gregory <ga...@gmail.com>
AuthorDate: Sun Sep 19 12:15:50 2021 -0400

    Method that allocates should release resources.
    
    Use try-with-resources with Tailer as an AutoCloseable.
    All tests now manage its own resource.
---
 .../java/org/apache/commons/io/input/Tailer.java   |  17 +-
 .../org/apache/commons/io/input/TailerTest.java    | 456 +++++++++++----------
 2 files changed, 247 insertions(+), 226 deletions(-)

diff --git a/src/main/java/org/apache/commons/io/input/Tailer.java b/src/main/java/org/apache/commons/io/input/Tailer.java
index c881f32..349f848 100644
--- a/src/main/java/org/apache/commons/io/input/Tailer.java
+++ b/src/main/java/org/apache/commons/io/input/Tailer.java
@@ -155,7 +155,7 @@ import org.apache.commons.io.file.attribute.FileTimes;
  *        alternative libraries such as jCIFS or <a href="https://commons.apache.org/proper/commons-vfs/">Apache Commons
  *        VFS</a>.
  */
-public class Tailer implements Runnable {
+public class Tailer implements Runnable, AutoCloseable {
 
     /**
      * Builds a {@link Tailer} with default values.
@@ -769,6 +769,14 @@ public class Tailer implements Runnable {
     }
 
     /**
+     * Requests the tailer to complete its current loop and return.
+     */
+    @Override
+    public void close() {
+        this.run = false;
+    }
+
+    /**
      * Gets the delay in milliseconds.
      *
      * @return the delay in milliseconds.
@@ -963,14 +971,17 @@ public class Tailer implements Runnable {
             } catch (final IOException e) {
                 listener.handle(e);
             }
-            stop();
+            close();
         }
     }
 
     /**
      * Requests the tailer to complete its current loop and return.
+     *
+     * @deprecated Use {@link #close()}.
      */
+    @Deprecated
     public void stop() {
-        this.run = false;
+        close();
     }
 }
diff --git a/src/test/java/org/apache/commons/io/input/TailerTest.java b/src/test/java/org/apache/commons/io/input/TailerTest.java
index 97f8ea3..6ce918e 100644
--- a/src/test/java/org/apache/commons/io/input/TailerTest.java
+++ b/src/test/java/org/apache/commons/io/input/TailerTest.java
@@ -45,7 +45,6 @@ import java.util.concurrent.Executor;
 import java.util.concurrent.ScheduledThreadPoolExecutor;
 import java.util.concurrent.TimeUnit;
 
-import com.google.common.collect.Lists;
 import org.apache.commons.io.FileUtils;
 import org.apache.commons.io.IOUtils;
 import org.apache.commons.io.TestResources;
@@ -54,6 +53,8 @@ import org.junit.jupiter.api.AfterEach;
 import org.junit.jupiter.api.Test;
 import org.junit.jupiter.api.io.TempDir;
 
+import com.google.common.collect.Lists;
+
 /**
  * Test for {@link Tailer}.
  */
@@ -143,7 +144,7 @@ public class TailerTest {
             latch = new CountDownLatch(expectedLines);
         }
 
-        public boolean awaitExpectedLines(long timeout, TimeUnit timeUnit) throws InterruptedException {
+        public boolean awaitExpectedLines(final long timeout, final TimeUnit timeUnit) throws InterruptedException {
             return latch.await(timeout, timeUnit);
         }
 
@@ -190,8 +191,6 @@ public class TailerTest {
     @TempDir
     public static File temporaryFolder;
 
-    private Tailer tailer;
-
     protected void createFile(final File file, final long size) throws IOException {
         assertTrue(file.getParentFile().exists(), () -> "Cannot create file " + file + " as the parent directory does not exist");
         try (final BufferedOutputStream output = new BufferedOutputStream(Files.newOutputStream(file.toPath()))) {
@@ -215,13 +214,6 @@ public class TailerTest {
         }
     }
 
-    @AfterEach
-    public void tearDown() {
-        if (tailer != null) {
-            tailer.stop();
-        }
-    }
-
     @Test
     @SuppressWarnings("squid:S2699") // Suppress "Add at least one assertion to this test case"
     public void testBufferBreak() throws Exception {
@@ -232,17 +224,17 @@ public class TailerTest {
         writeString(file, "SBTOURIST\n");
 
         final TestTailerListener listener = new TestTailerListener();
-        tailer = new Tailer(file, listener, delay, false, 1);
+        try (Tailer tailer = new Tailer(file, listener, delay, false, 1)) {
+            final Thread thread = new Thread(tailer);
+            thread.start();
 
-        final Thread thread = new Thread(tailer);
-        thread.start();
+            List<String> lines = listener.getLines();
+            while (lines.isEmpty() || !lines.get(lines.size() - 1).equals("SBTOURIST")) {
+                lines = listener.getLines();
+            }
 
-        List<String> lines = listener.getLines();
-        while (lines.isEmpty() || !lines.get(lines.size() - 1).equals("SBTOURIST")) {
-            lines = listener.getLines();
+            listener.clear();
         }
-
-        listener.clear();
     }
 
     @Test
@@ -250,9 +242,10 @@ public class TailerTest {
         final File file = new File(temporaryFolder, "tailer-create-with-delay-and-from-start-with-reopen-and-buffersize-and-charset.txt");
         createFile(file, 0);
         final TestTailerListener listener = new TestTailerListener(1);
-        final Tailer tailer = new Tailer.Builder(new NonStandardTailable(file), listener).build();
-        assertTrue(tailer.getTailable() instanceof NonStandardTailable);
-        validateTailer(listener, tailer, file);
+        try (final Tailer tailer = new Tailer.Builder(new NonStandardTailable(file), listener).build()) {
+            assertTrue(tailer.getTailable() instanceof NonStandardTailable);
+            validateTailer(listener, tailer, file);
+        }
     }
 
     @Test
@@ -260,8 +253,9 @@ public class TailerTest {
         final File file = new File(temporaryFolder, "tailer-create.txt");
         createFile(file, 0);
         final TestTailerListener listener = new TestTailerListener(1);
-        final Tailer tailer = Tailer.create(file, listener);
-        validateTailer(listener, tailer, file);
+        try (final Tailer tailer = Tailer.create(file, listener)) {
+            validateTailer(listener, tailer, file);
+        }
     }
 
     @Test
@@ -269,8 +263,9 @@ public class TailerTest {
         final File file = new File(temporaryFolder, "tailer-create-with-delay-and-from-start-with-reopen.txt");
         createFile(file, 0);
         final TestTailerListener listener = new TestTailerListener(1);
-        final Tailer tailer = Tailer.create(file, listener, TEST_DELAY_MILLIS, false, false);
-        validateTailer(listener, tailer, file);
+        try (final Tailer tailer = Tailer.create(file, listener, TEST_DELAY_MILLIS, false, false)) {
+            validateTailer(listener, tailer, file);
+        }
     }
 
     @Test
@@ -278,8 +273,9 @@ public class TailerTest {
         final File file = new File(temporaryFolder, "tailer-create-with-delay.txt");
         createFile(file, 0);
         final TestTailerListener listener = new TestTailerListener(1);
-        final Tailer tailer = Tailer.create(file, listener, TEST_DELAY_MILLIS);
-        validateTailer(listener, tailer, file);
+        try (final Tailer tailer = Tailer.create(file, listener, TEST_DELAY_MILLIS)) {
+            validateTailer(listener, tailer, file);
+        }
     }
 
     @Test
@@ -287,8 +283,9 @@ public class TailerTest {
         final File file = new File(temporaryFolder, "tailer-create-with-delay-and-from-start.txt");
         createFile(file, 0);
         final TestTailerListener listener = new TestTailerListener(1);
-        final Tailer tailer = Tailer.create(file, listener, TEST_DELAY_MILLIS, false);
-        validateTailer(listener, tailer, file);
+        try (final Tailer tailer = Tailer.create(file, listener, TEST_DELAY_MILLIS, false)) {
+            validateTailer(listener, tailer, file);
+        }
     }
 
     @Test
@@ -296,8 +293,9 @@ public class TailerTest {
         final File file = new File(temporaryFolder, "tailer-create-with-delay-and-from-start-with-buffersize.txt");
         createFile(file, 0);
         final TestTailerListener listener = new TestTailerListener(1);
-        final Tailer tailer = Tailer.create(file, listener, TEST_DELAY_MILLIS, false, TEST_BUFFER_SIZE);
-        validateTailer(listener, tailer, file);
+        try (final Tailer tailer = Tailer.create(file, listener, TEST_DELAY_MILLIS, false, TEST_BUFFER_SIZE)) {
+            validateTailer(listener, tailer, file);
+        }
     }
 
     @Test
@@ -305,8 +303,9 @@ public class TailerTest {
         final File file = new File(temporaryFolder, "tailer-create-with-delay-and-from-start-with-reopen-and-buffersize.txt");
         createFile(file, 0);
         final TestTailerListener listener = new TestTailerListener(1);
-        final Tailer tailer = Tailer.create(file, listener, TEST_DELAY_MILLIS, false, true, TEST_BUFFER_SIZE);
-        validateTailer(listener, tailer, file);
+        try (final Tailer tailer = Tailer.create(file, listener, TEST_DELAY_MILLIS, false, true, TEST_BUFFER_SIZE)) {
+            validateTailer(listener, tailer, file);
+        }
     }
 
     @Test
@@ -314,8 +313,9 @@ public class TailerTest {
         final File file = new File(temporaryFolder, "tailer-create-with-delay-and-from-start-with-reopen-and-buffersize-and-charset.txt");
         createFile(file, 0);
         final TestTailerListener listener = new TestTailerListener(1);
-        final Tailer tailer = Tailer.create(file, StandardCharsets.UTF_8, listener, TEST_DELAY_MILLIS, false, true, TEST_BUFFER_SIZE);
-        validateTailer(listener, tailer, file);
+        try (final Tailer tailer = Tailer.create(file, StandardCharsets.UTF_8, listener, TEST_DELAY_MILLIS, false, true, TEST_BUFFER_SIZE)) {
+            validateTailer(listener, tailer, file);
+        }
     }
 
     /*
@@ -329,19 +329,20 @@ public class TailerTest {
         // Use a long delay to try to make sure the test thread calls interrupt() while the tailer thread is sleeping.
         final int delay = 1000;
         final int idle = 50; // allow time for thread to work
-        tailer = new Tailer(file, listener, delay, false, IOUtils.DEFAULT_BUFFER_SIZE);
-        final Thread thread = new Thread(tailer);
-        thread.setDaemon(true);
-        thread.start();
-        TestUtils.sleep(idle);
-        thread.interrupt();
-        TestUtils.sleep(delay + idle);
-        assertNotNull(listener.exception, "Missing InterruptedException");
-        assertTrue(listener.exception instanceof InterruptedException, "Unexpected Exception: " + listener.exception);
-        assertEquals(1, listener.initialized, "Expected init to be called");
-        assertTrue(listener.notFound > 0, "fileNotFound should be called");
-        assertEquals(0, listener.rotated, "fileRotated should be not be called");
-        assertEquals(0, listener.reachedEndOfFile, "end of file never reached");
+        try (Tailer tailer = new Tailer(file, listener, delay, false, IOUtils.DEFAULT_BUFFER_SIZE)) {
+            final Thread thread = new Thread(tailer);
+            thread.setDaemon(true);
+            thread.start();
+            TestUtils.sleep(idle);
+            thread.interrupt();
+            TestUtils.sleep(delay + idle);
+            assertNotNull(listener.exception, "Missing InterruptedException");
+            assertTrue(listener.exception instanceof InterruptedException, "Unexpected Exception: " + listener.exception);
+            assertEquals(1, listener.initialized, "Expected init to be called");
+            assertTrue(listener.notFound > 0, "fileNotFound should be called");
+            assertEquals(0, listener.rotated, "fileRotated should be not be called");
+            assertEquals(0, listener.reachedEndOfFile, "end of file never reached");
+        }
     }
 
     @Test
@@ -351,20 +352,21 @@ public class TailerTest {
         final File file = new File(temporaryFolder, "tailer-testio334.txt");
         createFile(file, 0);
         final TestTailerListener listener = new TestTailerListener();
-        tailer = new Tailer(file, listener, delayMillis, false);
-        final Thread thread = new Thread(tailer);
-        thread.start();
+        try (Tailer tailer = new Tailer(file, listener, delayMillis, false)) {
+            final Thread thread = new Thread(tailer);
+            thread.start();
 
-        // Write some lines to the file
-        writeString(file, "CRLF\r\n", "LF\n", "CR\r", "CRCR\r\r", "trail");
-        final long testDelayMillis = delayMillis * 10;
-        TestUtils.sleep(testDelayMillis);
-        final List<String> lines = listener.getLines();
-        assertEquals(4, lines.size(), "line count");
-        assertEquals("CRLF", lines.get(0), "line 1");
-        assertEquals("LF", lines.get(1), "line 2");
-        assertEquals("CR", lines.get(2), "line 3");
-        assertEquals("CRCR\r", lines.get(3), "line 4");
+            // Write some lines to the file
+            writeString(file, "CRLF\r\n", "LF\n", "CR\r", "CRCR\r\r", "trail");
+            final long testDelayMillis = delayMillis * 10;
+            TestUtils.sleep(testDelayMillis);
+            final List<String> lines = listener.getLines();
+            assertEquals(4, lines.size(), "line count");
+            assertEquals("CRLF", lines.get(0), "line 1");
+            assertEquals("LF", lines.get(1), "line 2");
+            assertEquals("CR", lines.get(2), "line 3");
+            assertEquals("CRCR\r", lines.get(3), "line 4");
+        }
     }
 
     @Test
@@ -382,20 +384,21 @@ public class TailerTest {
         }
 
         final TestTailerListener listener = new TestTailerListener();
-        tailer = new Tailer(file, listener, delay, false);
+        try (Tailer tailer = new Tailer(file, listener, delay, false)) {
 
-        // final long start = System.currentTimeMillis();
+            // final long start = System.currentTimeMillis();
 
-        final Thread thread = new Thread(tailer);
-        thread.start();
+            final Thread thread = new Thread(tailer);
+            thread.start();
 
-        List<String> lines = listener.getLines();
-        while (lines.isEmpty() || !lines.get(lines.size() - 1).equals("SBTOURIST")) {
-            lines = listener.getLines();
-        }
-        // System.out.println("Elapsed: " + (System.currentTimeMillis() - start));
+            List<String> lines = listener.getLines();
+            while (lines.isEmpty() || !lines.get(lines.size() - 1).equals("SBTOURIST")) {
+                lines = listener.getLines();
+            }
+            // System.out.println("Elapsed: " + (System.currentTimeMillis() - start));
 
-        listener.clear();
+            listener.clear();
+        }
     }
 
     @Test
@@ -410,30 +413,31 @@ public class TailerTest {
         final boolean isWindows = osname.startsWith("Windows");
         // Need to use UTF-8 to read & write the file otherwise it can be corrupted (depending on the default charset)
         final Charset charsetUTF8 = StandardCharsets.UTF_8;
-        tailer = new Tailer(file, charsetUTF8, listener, delay, false, isWindows, IOUtils.DEFAULT_BUFFER_SIZE);
-        final Thread thread = new Thread(tailer);
-        thread.start();
-
-        try (Writer out = new OutputStreamWriter(Files.newOutputStream(file.toPath()), charsetUTF8);
-            BufferedReader reader = new BufferedReader(new InputStreamReader(Files.newInputStream(origin.toPath()), charsetUTF8))) {
-            final List<String> lines = new ArrayList<>();
-            String line;
-            while ((line = reader.readLine()) != null) {
-                out.write(line);
-                out.write("\n");
-                lines.add(line);
-            }
-            out.close(); // ensure data is written
-
-            final long testDelayMillis = delay * 10;
-            TestUtils.sleep(testDelayMillis);
-            final List<String> tailerlines = listener.getLines();
-            assertEquals(lines.size(), tailerlines.size(), "line count");
-            for (int i = 0, len = lines.size(); i < len; i++) {
-                final String expected = lines.get(i);
-                final String actual = tailerlines.get(i);
-                if (!expected.equals(actual)) {
-                    fail("Line: " + i + "\nExp: (" + expected.length() + ") " + expected + "\nAct: (" + actual.length() + ") " + actual);
+        try (Tailer tailer = new Tailer(file, charsetUTF8, listener, delay, false, isWindows, IOUtils.DEFAULT_BUFFER_SIZE)) {
+            final Thread thread = new Thread(tailer);
+            thread.start();
+
+            try (Writer out = new OutputStreamWriter(Files.newOutputStream(file.toPath()), charsetUTF8);
+                BufferedReader reader = new BufferedReader(new InputStreamReader(Files.newInputStream(origin.toPath()), charsetUTF8))) {
+                final List<String> lines = new ArrayList<>();
+                String line;
+                while ((line = reader.readLine()) != null) {
+                    out.write(line);
+                    out.write("\n");
+                    lines.add(line);
+                }
+                out.close(); // ensure data is written
+
+                final long testDelayMillis = delay * 10;
+                TestUtils.sleep(testDelayMillis);
+                final List<String> tailerlines = listener.getLines();
+                assertEquals(lines.size(), tailerlines.size(), "line count");
+                for (int i = 0, len = lines.size(); i < len; i++) {
+                    final String expected = lines.get(i);
+                    final String actual = tailerlines.get(i);
+                    if (!expected.equals(actual)) {
+                        fail("Line: " + i + "\nExp: (" + expected.length() + ") " + expected + "\nAct: (" + actual.length() + ") " + actual);
+                    }
                 }
             }
         }
@@ -444,10 +448,11 @@ public class TailerTest {
         final File file = new File(temporaryFolder, "tailer-simple-constructor.txt");
         createFile(file, 0);
         final TestTailerListener listener = new TestTailerListener(1);
-        final Tailer tailer = new Tailer(file, listener);
-        final Thread thread = new Thread(tailer);
-        thread.start();
-        validateTailer(listener, tailer, file);
+        try (final Tailer tailer = new Tailer(file, listener)) {
+            final Thread thread = new Thread(tailer);
+            thread.start();
+            validateTailer(listener, tailer, file);
+        }
     }
 
     @Test
@@ -455,10 +460,11 @@ public class TailerTest {
         final File file = new File(temporaryFolder, "tailer-simple-constructor-with-delay.txt");
         createFile(file, 0);
         final TestTailerListener listener = new TestTailerListener(1);
-        final Tailer tailer = new Tailer(file, listener, TEST_DELAY_MILLIS);
-        final Thread thread = new Thread(tailer);
-        thread.start();
-        validateTailer(listener, tailer, file);
+        try (final Tailer tailer = new Tailer(file, listener, TEST_DELAY_MILLIS)) {
+            final Thread thread = new Thread(tailer);
+            thread.start();
+            validateTailer(listener, tailer, file);
+        }
     }
 
     @Test
@@ -466,10 +472,11 @@ public class TailerTest {
         final File file = new File(temporaryFolder, "tailer-simple-constructor-with-delay-and-from-start.txt");
         createFile(file, 0);
         final TestTailerListener listener = new TestTailerListener(1);
-        final Tailer tailer = new Tailer(file, listener, TEST_DELAY_MILLIS, false);
-        final Thread thread = new Thread(tailer);
-        thread.start();
-        validateTailer(listener, tailer, file);
+        try (final Tailer tailer = new Tailer(file, listener, TEST_DELAY_MILLIS, false)) {
+            final Thread thread = new Thread(tailer);
+            thread.start();
+            validateTailer(listener, tailer, file);
+        }
     }
 
     @Test
@@ -477,10 +484,11 @@ public class TailerTest {
         final File file = new File(temporaryFolder, "tailer-simple-constructor-with-delay-and-from-start-with-buffersize.txt");
         createFile(file, 0);
         final TestTailerListener listener = new TestTailerListener(1);
-        final Tailer tailer = new Tailer(file, listener, TEST_DELAY_MILLIS, false, TEST_BUFFER_SIZE);
-        final Thread thread = new Thread(tailer);
-        thread.start();
-        validateTailer(listener, tailer, file);
+        try (final Tailer tailer = new Tailer(file, listener, TEST_DELAY_MILLIS, false, TEST_BUFFER_SIZE)) {
+            final Thread thread = new Thread(tailer);
+            thread.start();
+            validateTailer(listener, tailer, file);
+        }
     }
 
     @Test
@@ -488,10 +496,11 @@ public class TailerTest {
         final File file = new File(temporaryFolder, "tailer-simple-constructor-with-delay-and-from-start-with-reopen.txt");
         createFile(file, 0);
         final TestTailerListener listener = new TestTailerListener(1);
-        final Tailer tailer = new Tailer(file, listener, TEST_DELAY_MILLIS, false, false);
-        final Thread thread = new Thread(tailer);
-        thread.start();
-        validateTailer(listener, tailer, file);
+        try (final Tailer tailer = new Tailer(file, listener, TEST_DELAY_MILLIS, false, false)) {
+            final Thread thread = new Thread(tailer);
+            thread.start();
+            validateTailer(listener, tailer, file);
+        }
     }
 
     @Test
@@ -499,10 +508,11 @@ public class TailerTest {
         final File file = new File(temporaryFolder, "tailer-simple-constructor-with-delay-and-from-start-with-reopen-and-buffersize.txt");
         createFile(file, 0);
         final TestTailerListener listener = new TestTailerListener(1);
-        final Tailer tailer = new Tailer(file, listener, TEST_DELAY_MILLIS, false, true, TEST_BUFFER_SIZE);
-        final Thread thread = new Thread(tailer);
-        thread.start();
-        validateTailer(listener, tailer, file);
+        try (final Tailer tailer = new Tailer(file, listener, TEST_DELAY_MILLIS, false, true, TEST_BUFFER_SIZE)) {
+            final Thread thread = new Thread(tailer);
+            thread.start();
+            validateTailer(listener, tailer, file);
+        }
     }
 
     @Test
@@ -510,10 +520,11 @@ public class TailerTest {
         final File file = new File(temporaryFolder, "tailer-simple-constructor-with-delay-and-from-start-with-reopen-and-buffersize-and-charset.txt");
         createFile(file, 0);
         final TestTailerListener listener = new TestTailerListener(1);
-        final Tailer tailer = new Tailer(file, StandardCharsets.UTF_8, listener, TEST_DELAY_MILLIS, false, true, TEST_BUFFER_SIZE);
-        final Thread thread = new Thread(tailer);
-        thread.start();
-        validateTailer(listener, tailer, file);
+        try (final Tailer tailer = new Tailer(file, StandardCharsets.UTF_8, listener, TEST_DELAY_MILLIS, false, true, TEST_BUFFER_SIZE)) {
+            final Thread thread = new Thread(tailer);
+            thread.start();
+            validateTailer(listener, tailer, file);
+        }
     }
 
     @Test
@@ -523,9 +534,9 @@ public class TailerTest {
         final TestTailerListener listener = new TestTailerListener();
         final int delay = 100;
         final int idle = 50; // allow time for thread to work
-        tailer = Tailer.create(file, listener, delay, false);
-        TestUtils.sleep(idle);
-        tailer.stop();
+        try (Tailer tailer = Tailer.create(file, listener, delay, false)) {
+            TestUtils.sleep(idle);
+        }
         TestUtils.sleep(delay + idle);
         assertNull(listener.exception, "Should not generate Exception");
         assertEquals(1, listener.initialized, "Expected init to be called");
@@ -541,11 +552,11 @@ public class TailerTest {
         final TestTailerListener listener = new TestTailerListener();
         final int delay = 100;
         final int idle = 50; // allow time for thread to work
-        tailer = new Tailer(file, listener, delay, false);
-        final Executor exec = new ScheduledThreadPoolExecutor(1);
-        exec.execute(tailer);
-        TestUtils.sleep(idle);
-        tailer.stop();
+        try (Tailer tailer = new Tailer(file, listener, delay, false)) {
+            final Executor exec = new ScheduledThreadPoolExecutor(1);
+            exec.execute(tailer);
+            TestUtils.sleep(idle);
+        }
         TestUtils.sleep(delay + idle);
         assertNull(listener.exception, "Should not generate Exception");
         assertEquals(1, listener.initialized, "Expected init to be called");
@@ -564,61 +575,62 @@ public class TailerTest {
         final TestTailerListener listener = new TestTailerListener();
         final String osname = System.getProperty("os.name");
         final boolean isWindows = osname.startsWith("Windows");
-        tailer = new Tailer(file, listener, delayMillis, false, isWindows);
-        final Thread thread = new Thread(tailer);
-        thread.start();
+        try (Tailer tailer = new Tailer(file, listener, delayMillis, false, isWindows)) {
+            final Thread thread = new Thread(tailer);
+            thread.start();
 
-        // Write some lines to the file
-        write(file, "Line one", "Line two");
-        final long testDelayMillis = delayMillis * 10;
-        TestUtils.sleep(testDelayMillis);
-        List<String> lines = listener.getLines();
-        assertEquals(2, lines.size(), "1 line count");
-        assertEquals("Line one", lines.get(0), "1 line 1");
-        assertEquals("Line two", lines.get(1), "1 line 2");
-        listener.clear();
-
-        // Write another line to the file
-        write(file, "Line three");
-        TestUtils.sleep(testDelayMillis);
-        lines = listener.getLines();
-        assertEquals(1, lines.size(), "2 line count");
-        assertEquals("Line three", lines.get(0), "2 line 3");
-        listener.clear();
-
-        // Check file does actually have all the lines
-        lines = FileUtils.readLines(file, "UTF-8");
-        assertEquals(3, lines.size(), "3 line count");
-        assertEquals("Line one", lines.get(0), "3 line 1");
-        assertEquals("Line two", lines.get(1), "3 line 2");
-        assertEquals("Line three", lines.get(2), "3 line 3");
-
-        // Delete & re-create
-        file.delete();
-        assertFalse(file.exists(), "File should not exist");
-        createFile(file, 0);
-        assertTrue(file.exists(), "File should now exist");
-        TestUtils.sleep(testDelayMillis);
-
-        // Write another line
-        write(file, "Line four");
-        TestUtils.sleep(testDelayMillis);
-        lines = listener.getLines();
-        assertEquals(1, lines.size(), "4 line count");
-        assertEquals("Line four", lines.get(0), "4 line 3");
-        listener.clear();
-
-        // Stop
-        thread.interrupt();
-        TestUtils.sleep(testDelayMillis * 4);
-        write(file, "Line five");
-        assertEquals(0, listener.getLines().size(), "4 line count");
-        assertNotNull(listener.exception, "Missing InterruptedException");
-        assertTrue(listener.exception instanceof InterruptedException, "Unexpected Exception: " + listener.exception);
-        assertEquals(1, listener.initialized, "Expected init to be called");
-        // assertEquals(0 , listener.notFound, "fileNotFound should not be called"); // there is a window when it might be
-        // called
-        assertEquals(1, listener.rotated, "fileRotated should be be called");
+            // Write some lines to the file
+            write(file, "Line one", "Line two");
+            final long testDelayMillis = delayMillis * 10;
+            TestUtils.sleep(testDelayMillis);
+            List<String> lines = listener.getLines();
+            assertEquals(2, lines.size(), "1 line count");
+            assertEquals("Line one", lines.get(0), "1 line 1");
+            assertEquals("Line two", lines.get(1), "1 line 2");
+            listener.clear();
+
+            // Write another line to the file
+            write(file, "Line three");
+            TestUtils.sleep(testDelayMillis);
+            lines = listener.getLines();
+            assertEquals(1, lines.size(), "2 line count");
+            assertEquals("Line three", lines.get(0), "2 line 3");
+            listener.clear();
+
+            // Check file does actually have all the lines
+            lines = FileUtils.readLines(file, "UTF-8");
+            assertEquals(3, lines.size(), "3 line count");
+            assertEquals("Line one", lines.get(0), "3 line 1");
+            assertEquals("Line two", lines.get(1), "3 line 2");
+            assertEquals("Line three", lines.get(2), "3 line 3");
+
+            // Delete & re-create
+            file.delete();
+            assertFalse(file.exists(), "File should not exist");
+            createFile(file, 0);
+            assertTrue(file.exists(), "File should now exist");
+            TestUtils.sleep(testDelayMillis);
+
+            // Write another line
+            write(file, "Line four");
+            TestUtils.sleep(testDelayMillis);
+            lines = listener.getLines();
+            assertEquals(1, lines.size(), "4 line count");
+            assertEquals("Line four", lines.get(0), "4 line 3");
+            listener.clear();
+
+            // Stop
+            thread.interrupt();
+            TestUtils.sleep(testDelayMillis * 4);
+            write(file, "Line five");
+            assertEquals(0, listener.getLines().size(), "4 line count");
+            assertNotNull(listener.exception, "Missing InterruptedException");
+            assertTrue(listener.exception instanceof InterruptedException, "Unexpected Exception: " + listener.exception);
+            assertEquals(1, listener.initialized, "Expected init to be called");
+            // assertEquals(0 , listener.notFound, "fileNotFound should not be called"); // there is a window when it might be
+            // called
+            assertEquals(1, listener.rotated, "fileRotated should be be called");
+        }
     }
 
     @Test
@@ -631,24 +643,25 @@ public class TailerTest {
         final TestTailerListener listener = new TestTailerListener();
         final String osname = System.getProperty("os.name");
         final boolean isWindows = osname.startsWith("Windows");
-        tailer = new Tailer(file, listener, delayMillis, false, isWindows);
-        final Thread thread = new Thread(tailer);
-        thread.start();
+        try (Tailer tailer = new Tailer(file, listener, delayMillis, false, isWindows)) {
+            final Thread thread = new Thread(tailer);
+            thread.start();
 
-        // write a few lines
-        write(file, "line1", "line2", "line3");
-        TestUtils.sleep(testDelayMillis);
+            // write a few lines
+            write(file, "line1", "line2", "line3");
+            TestUtils.sleep(testDelayMillis);
 
-        // write a few lines
-        write(file, "line4", "line5", "line6");
-        TestUtils.sleep(testDelayMillis);
+            // write a few lines
+            write(file, "line4", "line5", "line6");
+            TestUtils.sleep(testDelayMillis);
 
-        // write a few lines
-        write(file, "line7", "line8", "line9");
-        TestUtils.sleep(testDelayMillis);
+            // write a few lines
+            write(file, "line7", "line8", "line9");
+            TestUtils.sleep(testDelayMillis);
 
-        // May be > 3 times due to underlying OS behavior wrt streams
-        assertTrue(listener.reachedEndOfFile >= 3, "end of file reached at least 3 times");
+            // May be > 3 times due to underlying OS behavior wrt streams
+            assertTrue(listener.reachedEndOfFile >= 3, "end of file reached at least 3 times");
+        }
     }
 
     @Test
@@ -658,37 +671,34 @@ public class TailerTest {
         final File file = new File(temporaryFolder, "tailer2-test.txt");
         createFile(file, 0);
         final TestTailerListener listener = new TestTailerListener();
-        tailer = new Tailer(file, listener, delay, false);
-        final Thread thread = new Thread(tailer);
-        thread.start();
+        try (Tailer tailer = new Tailer(file, listener, delay, false)) {
+            final Thread thread = new Thread(tailer);
+            thread.start();
 
-        // Write some lines to the file
-        writeString(file, "Line");
+            // Write some lines to the file
+            writeString(file, "Line");
 
-        TestUtils.sleep(delay * 2);
-        List<String> lines = listener.getLines();
-        assertEquals(0, lines.size(), "1 line count");
+            TestUtils.sleep(delay * 2);
+            List<String> lines = listener.getLines();
+            assertEquals(0, lines.size(), "1 line count");
 
-        writeString(file, " one\n");
-        TestUtils.sleep(delay * 2);
-        lines = listener.getLines();
+            writeString(file, " one\n");
+            TestUtils.sleep(delay * 2);
+            lines = listener.getLines();
 
-        assertEquals(1, lines.size(), "1 line count");
-        assertEquals("Line one", lines.get(0), "1 line 1");
+            assertEquals(1, lines.size(), "1 line count");
+            assertEquals("Line one", lines.get(0), "1 line 1");
 
-        listener.clear();
+            listener.clear();
+        }
     }
 
     private void validateTailer(final TestTailerListener listener, final Tailer tailer, final File file) throws Exception {
-        try {
-            write(file, "foo");
-            final int timeout = 30;
-            final TimeUnit timeoutUnit = TimeUnit.SECONDS;
-            assertTrue(listener.awaitExpectedLines(timeout, timeoutUnit), () -> String.format("await timed out after %s %s", timeout, timeoutUnit));
-            assertEquals(listener.getLines(), Lists.newArrayList("foo"), "lines");
-        } finally {
-            tailer.stop();
-        }
+        write(file, "foo");
+        final int timeout = 30;
+        final TimeUnit timeoutUnit = TimeUnit.SECONDS;
+        assertTrue(listener.awaitExpectedLines(timeout, timeoutUnit), () -> String.format("await timed out after %s %s", timeout, timeoutUnit));
+        assertEquals(listener.getLines(), Lists.newArrayList("foo"), "lines");
     }
 
     /** Appends lines to a file */