|
|
|
@ -17,6 +17,7 @@
|
|
|
|
|
package org.springframework.boot.devtools.restart.classloader;
|
|
|
|
|
|
|
|
|
|
import java.io.IOException;
|
|
|
|
|
import java.lang.reflect.Method;
|
|
|
|
|
import java.net.MalformedURLException;
|
|
|
|
|
import java.net.URL;
|
|
|
|
|
import java.net.URLClassLoader;
|
|
|
|
@ -30,6 +31,7 @@ import org.apache.commons.logging.LogFactory;
|
|
|
|
|
import org.springframework.boot.devtools.restart.classloader.ClassLoaderFile.Kind;
|
|
|
|
|
import org.springframework.core.SmartClassLoader;
|
|
|
|
|
import org.springframework.util.Assert;
|
|
|
|
|
import org.springframework.util.ReflectionUtils;
|
|
|
|
|
|
|
|
|
|
/**
|
|
|
|
|
* Disposable {@link ClassLoader} used to support application restarting. Provides parent
|
|
|
|
@ -41,6 +43,8 @@ import org.springframework.util.Assert;
|
|
|
|
|
*/
|
|
|
|
|
public class RestartClassLoader extends URLClassLoader implements SmartClassLoader {
|
|
|
|
|
|
|
|
|
|
private final ClassLoadingLockSupplier classLoadingLockSupplier;
|
|
|
|
|
|
|
|
|
|
private final Log logger;
|
|
|
|
|
|
|
|
|
|
private final ClassLoaderFileRepository updatedFiles;
|
|
|
|
@ -85,6 +89,11 @@ public class RestartClassLoader extends URLClassLoader implements SmartClassLoad
|
|
|
|
|
if (logger.isDebugEnabled()) {
|
|
|
|
|
logger.debug("Created RestartClassLoader " + toString());
|
|
|
|
|
}
|
|
|
|
|
Method classLoadingLockMethod = ReflectionUtils.findMethod(ClassLoader.class,
|
|
|
|
|
"getClassLoadingLock", String.class);
|
|
|
|
|
this.classLoadingLockSupplier = classLoadingLockMethod != null
|
|
|
|
|
? new StandardClassLoadingLockSupplier()
|
|
|
|
|
: new Java6ClassLoadingLockSupplier();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
@ -142,7 +151,7 @@ public class RestartClassLoader extends URLClassLoader implements SmartClassLoad
|
|
|
|
|
if (file != null && file.getKind() == Kind.DELETED) {
|
|
|
|
|
throw new ClassNotFoundException(name);
|
|
|
|
|
}
|
|
|
|
|
synchronized (getClassLoadingLock(name)) {
|
|
|
|
|
synchronized (this.classLoadingLockSupplier.getClassLoadingLock(this, name)) {
|
|
|
|
|
Class<?> loadedClass = findLoadedClass(name);
|
|
|
|
|
if (loadedClass == null) {
|
|
|
|
|
try {
|
|
|
|
@ -232,4 +241,32 @@ public class RestartClassLoader extends URLClassLoader implements SmartClassLoad
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private interface ClassLoadingLockSupplier {
|
|
|
|
|
|
|
|
|
|
Object getClassLoadingLock(RestartClassLoader classLoader, String className);
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private static final class Java6ClassLoadingLockSupplier
|
|
|
|
|
implements ClassLoadingLockSupplier {
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public Object getClassLoadingLock(RestartClassLoader classLoader,
|
|
|
|
|
String className) {
|
|
|
|
|
return classLoader;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private static final class StandardClassLoadingLockSupplier
|
|
|
|
|
implements ClassLoadingLockSupplier {
|
|
|
|
|
|
|
|
|
|
@Override
|
|
|
|
|
public Object getClassLoadingLock(RestartClassLoader classLoader,
|
|
|
|
|
String className) {
|
|
|
|
|
return classLoader.getClassLoadingLock(className);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|