From cd2c18965e595edfbe58b6a778ec8e1c97dbb862 Mon Sep 17 00:00:00 2001 From: Phillip Webb Date: Mon, 2 Sep 2013 13:38:23 -0700 Subject: [PATCH] Support javaagent instrumentation with loader Update spring-boot-loader to allow `-javaagent` instrumentation when running from executable jars. Prior to this commit the `Launcher` skipped the application classloader and instead used the system classloader as a parent. This was to ensure that locally packaged classes were always loaded by the classloader that had access to nested jars. Unfortunately when using the `-javaagent` option, it is the application classloader that is modified. The `Launcher` class now uses the application classloader as parent and `LaunchedURLClassLoader` has been updated to always search local URLs before delegating to the parent. This is very similar to the way that most application servers handle the loading of war files. Issue: #56232870 --- .../boot/loader/LaunchedURLClassLoader.java | 27 +++++++++++++++++++ .../springframework/boot/loader/Launcher.java | 2 +- 2 files changed, 28 insertions(+), 1 deletion(-) 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 19b21735191..871f4c95c2d 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 @@ -40,6 +40,33 @@ public class LaunchedURLClassLoader extends URLClassLoader { super(urls, parent); } + /** + * Attempt to load classes from the URLs before delegating to the parent loader. + */ + @Override + protected Class loadClass(String name, boolean resolve) + throws ClassNotFoundException { + synchronized (getClassLoadingLock(name)) { + Class loadedClass = findLoadedClass(name); + if (loadedClass == null) { + loadedClass = doLoadClass(name); + } + if (resolve) { + resolveClass(loadedClass); + } + return loadedClass; + } + } + + private Class doLoadClass(String name) throws ClassNotFoundException { + try { + return findClass(name); + } + catch (ClassNotFoundException e) { + } + return super.loadClass(name, false); + } + @Override protected Class findClass(final String name) throws ClassNotFoundException { int lastDot = name.lastIndexOf('.'); diff --git a/spring-boot-tools/spring-boot-loader/src/main/java/org/springframework/boot/loader/Launcher.java b/spring-boot-tools/spring-boot-loader/src/main/java/org/springframework/boot/loader/Launcher.java index 0f8991a30ca..8ab325434ff 100644 --- a/spring-boot-tools/spring-boot-loader/src/main/java/org/springframework/boot/loader/Launcher.java +++ b/spring-boot-tools/spring-boot-loader/src/main/java/org/springframework/boot/loader/Launcher.java @@ -143,7 +143,7 @@ public abstract class Launcher { * @throws Exception */ protected ClassLoader createClassLoader(URL[] urls) throws Exception { - return new LaunchedURLClassLoader(urls, getClass().getClassLoader().getParent()); + return new LaunchedURLClassLoader(urls, getClass().getClassLoader()); } /**