From 939b66f4eeb0e0f3d22e171306afe6fb9f5d9e20 Mon Sep 17 00:00:00 2001 From: Vladimir Tsanev Date: Mon, 23 Nov 2015 13:11:08 +0200 Subject: [PATCH] Use fast exceptions in findResource(s) Some libraries like aspectj are using findResource to see the raw bytecode of a class. It will even call findResource for every method of every class of beans that are post processed. This can be significant performance hit on startup when LaunchedURLClassLoader and there are a lot of nested jars. See gh-3640 Fixes gh-4557 --- .../boot/loader/LaunchedURLClassLoader.java | 86 ++++++++++++------- 1 file changed, 56 insertions(+), 30 deletions(-) diff --git a/spring-boot-tools/spring-boot-loader/src/main/java/org/springframework/boot/loader/LaunchedURLClassLoader.java b/spring-boot-tools/spring-boot-loader/src/main/java/org/springframework/boot/loader/LaunchedURLClassLoader.java index 94bdc73c57..28e5da3545 100644 --- a/spring-boot-tools/spring-boot-loader/src/main/java/org/springframework/boot/loader/LaunchedURLClassLoader.java +++ b/spring-boot-tools/spring-boot-loader/src/main/java/org/springframework/boot/loader/LaunchedURLClassLoader.java @@ -76,7 +76,13 @@ public class LaunchedURLClassLoader extends URLClassLoader { if (name.equals("") && hasURLs()) { return getURLs()[0]; } - return super.findResource(name); + Handler.setUseFastConnectionExceptions(true); + try { + return super.findResource(name); + } + finally { + Handler.setUseFastConnectionExceptions(false); + } } catch (IllegalArgumentException ex) { return null; @@ -88,7 +94,13 @@ public class LaunchedURLClassLoader extends URLClassLoader { if (name.equals("") && hasURLs()) { return Collections.enumeration(Arrays.asList(getURLs())); } - return super.findResources(name); + Handler.setUseFastConnectionExceptions(true); + try { + return super.findResources(name); + } + finally { + Handler.setUseFastConnectionExceptions(false); + } } private boolean hasURLs() { @@ -100,33 +112,8 @@ public class LaunchedURLClassLoader extends URLClassLoader { if (this.rootClassLoader == null) { return findResources(name); } - - final Enumeration rootResources = this.rootClassLoader.getResources(name); - final Enumeration localResources = findResources(name); - - return new Enumeration() { - - @Override - public boolean hasMoreElements() { - try { - Handler.setUseFastConnectionExceptions(true); - return rootResources.hasMoreElements() - || localResources.hasMoreElements(); - } - finally { - Handler.setUseFastConnectionExceptions(false); - } - } - - @Override - public URL nextElement() { - if (rootResources.hasMoreElements()) { - return rootResources.nextElement(); - } - return localResources.nextElement(); - } - - }; + return new ResourceEnumeration(this.rootClassLoader.getResources(name), + findResources(name)); } /** @@ -162,6 +149,7 @@ public class LaunchedURLClassLoader extends URLClassLoader { } } catch (Exception ex) { + } // 2) Try to find locally @@ -171,6 +159,7 @@ public class LaunchedURLClassLoader extends URLClassLoader { return cls; } catch (Exception ex) { + } // 3) Use standard loading @@ -265,4 +254,41 @@ public class LaunchedURLClassLoader extends URLClassLoader { } -} + /** + * {@link Enumeration} implementation used for {@code getResources()}. + */ + private static class ResourceEnumeration implements Enumeration { + + private final Enumeration rootResources; + + private final Enumeration localResources; + + ResourceEnumeration(Enumeration rootResources, + Enumeration localResources) { + this.rootResources = rootResources; + this.localResources = localResources; + } + + @Override + public boolean hasMoreElements() { + try { + Handler.setUseFastConnectionExceptions(true); + return this.rootResources.hasMoreElements() + || this.localResources.hasMoreElements(); + } + finally { + Handler.setUseFastConnectionExceptions(false); + } + } + + @Override + public URL nextElement() { + if (this.rootResources.hasMoreElements()) { + return this.rootResources.nextElement(); + } + return this.localResources.nextElement(); + } + + } + +} \ No newline at end of file