From 937f85765c7821ed3acb0679d1f98d73a7a9d327 Mon Sep 17 00:00:00 2001 From: hengyunabc Date: Thu, 18 Aug 2016 17:17:12 +0800 Subject: [PATCH 1/2] Ensure that LaunchedURLClassLoader works when thread is interrupted See gh-6683 --- .../loader/data/RandomAccessDataFile.java | 37 ++++++------------- 1 file changed, 12 insertions(+), 25 deletions(-) diff --git a/spring-boot-tools/spring-boot-loader/src/main/java/org/springframework/boot/loader/data/RandomAccessDataFile.java b/spring-boot-tools/spring-boot-loader/src/main/java/org/springframework/boot/loader/data/RandomAccessDataFile.java index 5ba87dcc850..6014e90fb08 100644 --- a/spring-boot-tools/spring-boot-loader/src/main/java/org/springframework/boot/loader/data/RandomAccessDataFile.java +++ b/spring-boot-tools/spring-boot-loader/src/main/java/org/springframework/boot/loader/data/RandomAccessDataFile.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2013 the original author or authors. + * Copyright 2012-2016 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -244,17 +244,10 @@ public class RandomAccessDataFile implements RandomAccessData { } public RandomAccessFile acquire() throws IOException { - try { - this.available.acquire(); - RandomAccessFile file = this.files.poll(); - return (file == null - ? new RandomAccessFile(RandomAccessDataFile.this.file, "r") - : file); - } - catch (InterruptedException ex) { - Thread.currentThread().interrupt(); - throw new IOException(ex); - } + this.available.acquireUninterruptibly(); + RandomAccessFile file = this.files.poll(); + return (file == null + ? new RandomAccessFile(RandomAccessDataFile.this.file, "r") : file); } public void release(RandomAccessFile file) { @@ -263,22 +256,16 @@ public class RandomAccessDataFile implements RandomAccessData { } public void close() throws IOException { + this.available.acquireUninterruptibly(this.size); try { - this.available.acquire(this.size); - try { - RandomAccessFile file = this.files.poll(); - while (file != null) { - file.close(); - file = this.files.poll(); - } - } - finally { - this.available.release(this.size); + RandomAccessFile file = this.files.poll(); + while (file != null) { + file.close(); + file = this.files.poll(); } } - catch (InterruptedException ex) { - Thread.currentThread().interrupt(); - throw new IOException(ex); + finally { + this.available.release(this.size); } } From 85c0b44dcbbe4d201f8b7fd72a97c31c2d07a3ec Mon Sep 17 00:00:00 2001 From: Andy Wilkinson Date: Thu, 18 Aug 2016 12:03:05 +0100 Subject: [PATCH 2/2] Test that LaunchedURLClassLoader works when thread is interrupted Previously, RandomAccessDataFile used a semaphore and acquired it interruptibly. This meant that an interrupted thread was unable to access the file. Notably, this would prevent LaunchedURLClassLoader from loading classes or resources on an interrupted thread. The previous commit (937f857) updates RandomAccessDataFile to acquire the semaphore uninterruptibly. This commit adds a test to LaunchedURLClassLoader to verify that it can now load a resource from an interrupted thread. Closes gh-6683 --- .../loader/LaunchedURLClassLoaderTests.java | 22 ++++++++++++++++++- 1 file changed, 21 insertions(+), 1 deletion(-) diff --git a/spring-boot-tools/spring-boot-loader/src/test/java/org/springframework/boot/loader/LaunchedURLClassLoaderTests.java b/spring-boot-tools/spring-boot-loader/src/test/java/org/springframework/boot/loader/LaunchedURLClassLoaderTests.java index 498796e7d92..8733a15051a 100644 --- a/spring-boot-tools/spring-boot-loader/src/test/java/org/springframework/boot/loader/LaunchedURLClassLoaderTests.java +++ b/spring-boot-tools/spring-boot-loader/src/test/java/org/springframework/boot/loader/LaunchedURLClassLoaderTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2014 the original author or authors. + * Copyright 2012-2016 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. @@ -36,6 +36,7 @@ import static org.junit.Assert.assertTrue; * * @author Dave Syer * @author Phillip Webb + * @author Andy Wilkinson */ @SuppressWarnings("resource") public class LaunchedURLClassLoaderTests { @@ -101,4 +102,23 @@ public class LaunchedURLClassLoaderTests { assertThat(resource.openConnection().getInputStream().read(), equalTo(3)); } + @Test + public void resolveFromNestedWhileThreadIsInterrupted() throws Exception { + File file = this.temporaryFolder.newFile(); + TestJarCreator.createTestJar(file); + JarFile jarFile = new JarFile(file); + URL url = jarFile.getUrl(); + LaunchedURLClassLoader loader = new LaunchedURLClassLoader(new URL[] { url }, + null); + try { + Thread.currentThread().interrupt(); + URL resource = loader.getResource("nested.jar!/3.dat"); + assertThat(resource.toString(), equalTo(url + "nested.jar!/3.dat")); + assertThat(resource.openConnection().getInputStream().read(), equalTo(3)); + } + finally { + Thread.interrupted(); + } + } + }