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
This commit is contained in:
Vladimir Tsanev 2015-11-23 13:11:08 +02:00 committed by Andy Wilkinson
parent 0214fe4b82
commit 939b66f4ee

View File

@ -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<URL> rootResources = this.rootClassLoader.getResources(name);
final Enumeration<URL> localResources = findResources(name);
return new Enumeration<URL>() {
@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<URL> {
private final Enumeration<URL> rootResources;
private final Enumeration<URL> localResources;
ResourceEnumeration(Enumeration<URL> rootResources,
Enumeration<URL> 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();
}
}
}