From e23bcdbe296506cdb047e609c0e471b867dedd77 Mon Sep 17 00:00:00 2001 From: Phillip Webb Date: Tue, 18 Mar 2014 12:05:35 -0700 Subject: [PATCH] Update OSX Java 1.6 compatibility fix for plugins Change the initial fix for OSX Java 1.6 compatibility by removing the need for a direct `tools.jar` dependency. It appears that `system` dependencies are always pulled in when used in a Maven plugin. This makes the the dependency on `tools.jar` particularly brittle since we need to make assumptions about where the jar is located. Since the tools jar is *only* needed for Spring Loaded support, the plugin has now been updated to locate the jar programmatically and call it via reflection. This should reduce the risk of problems when using the plugin and at the very least isolate them to Spring Loaded support. (See original commit b8c4720) Fixes gh-497 --- .../spring-boot-loader-tools/pom.xml | 31 ---------- .../boot/loader/tools/AgentAttacher.java | 21 ++++--- .../boot/loader/tools/JvmUtils.java | 61 +++++++++++++++++++ .../boot/loader/tools/JvmUtilsTests.java | 43 +++++++++++++ .../spring-boot-maven-plugin/pom.xml | 29 --------- 5 files changed, 117 insertions(+), 68 deletions(-) create mode 100644 spring-boot-tools/spring-boot-loader-tools/src/main/java/org/springframework/boot/loader/tools/JvmUtils.java create mode 100644 spring-boot-tools/spring-boot-loader-tools/src/test/java/org/springframework/boot/loader/tools/JvmUtilsTests.java diff --git a/spring-boot-tools/spring-boot-loader-tools/pom.xml b/spring-boot-tools/spring-boot-loader-tools/pom.xml index 40f93dd0b70..2045dfbc2d2 100644 --- a/spring-boot-tools/spring-boot-loader-tools/pom.xml +++ b/spring-boot-tools/spring-boot-loader-tools/pom.xml @@ -11,39 +11,8 @@ ${basedir}/../.. - - - standard-jdk - - - ${java.home}/../lib/tools.jar - - - - ${java.home}/../lib/tools.jar - - - - apple-jdk - - - ${java.home}/../Classes/classes.jar - - - - ${java.home}/../Classes/classes.jar - - - - - com.sun - tools - ${java.version} - system - ${tools-jar} - org.springframework spring-core diff --git a/spring-boot-tools/spring-boot-loader-tools/src/main/java/org/springframework/boot/loader/tools/AgentAttacher.java b/spring-boot-tools/spring-boot-loader-tools/src/main/java/org/springframework/boot/loader/tools/AgentAttacher.java index b6fe50e8a60..ea66a001853 100644 --- a/spring-boot-tools/spring-boot-loader-tools/src/main/java/org/springframework/boot/loader/tools/AgentAttacher.java +++ b/spring-boot-tools/spring-boot-loader-tools/src/main/java/org/springframework/boot/loader/tools/AgentAttacher.java @@ -18,10 +18,9 @@ package org.springframework.boot.loader.tools; import java.io.File; import java.lang.management.ManagementFactory; +import java.lang.reflect.Method; import java.util.List; -import com.sun.tools.attach.VirtualMachine; - /** * Utility class to attach an instrumentation agent to the running JVM. * @@ -29,16 +28,22 @@ import com.sun.tools.attach.VirtualMachine; */ public abstract class AgentAttacher { + private static final String VIRTUAL_MACHINE_CLASSNAME = "com.sun.tools.attach.VirtualMachine"; + public static void attach(File agent) { - String name = ManagementFactory.getRuntimeMXBean().getName(); - String pid = name.substring(0, name.indexOf('@')); try { - VirtualMachine vm = VirtualMachine.attach(pid); - vm.loadAgent(agent.getAbsolutePath()); - vm.detach(); + String name = ManagementFactory.getRuntimeMXBean().getName(); + String pid = name.substring(0, name.indexOf('@')); + ClassLoader classLoader = JvmUtils.getToolsClassLoader(); + Class vmClass = classLoader.loadClass(VIRTUAL_MACHINE_CLASSNAME); + Method attachMethod = vmClass.getDeclaredMethod("attach", String.class); + Object vm = attachMethod.invoke(null, pid); + Method loadAgentMethod = vmClass.getDeclaredMethod("loadAgent", String.class); + loadAgentMethod.invoke(vm, agent.getAbsolutePath()); + vmClass.getDeclaredMethod("detach").invoke(vm); } catch (Exception ex) { - throw new RuntimeException(ex); + throw new RuntimeException("Unable to attach Spring Loaded to the JVM", ex); } } diff --git a/spring-boot-tools/spring-boot-loader-tools/src/main/java/org/springframework/boot/loader/tools/JvmUtils.java b/spring-boot-tools/spring-boot-loader-tools/src/main/java/org/springframework/boot/loader/tools/JvmUtils.java new file mode 100644 index 00000000000..e96a01baf8d --- /dev/null +++ b/spring-boot-tools/spring-boot-loader-tools/src/main/java/org/springframework/boot/loader/tools/JvmUtils.java @@ -0,0 +1,61 @@ +/* + * Copyright 2012-2014 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. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.boot.loader.tools; + +import java.io.File; +import java.net.URL; +import java.net.URLClassLoader; + +/** + * Java Virtual Machine Utils. + * + * @author Phillip Webb + */ +abstract class JvmUtils { + + /** + * Various search locations for tools, including the odd Java 6 OSX jar + */ + private static final String[] TOOLS_LOCATIONS = { "lib/tools.jar", + "../lib/tools.jar", "../Classes/classes.jar" }; + + public static ClassLoader getToolsClassLoader() { + ClassLoader systemClassLoader = ClassLoader.getSystemClassLoader(); + return new URLClassLoader(new URL[] { getToolsJarUrl() }, systemClassLoader); + } + + public static URL getToolsJarUrl() { + String javaHome = getJavaHome(); + for (String location : TOOLS_LOCATIONS) { + try { + URL url = new URL("file://" + javaHome + "/" + location); + if (new File(url.toURI()).exists()) { + return url; + } + } + catch (Exception ex) { + // Ignore and try the next location + } + } + throw new IllegalStateException("Unable to locate tools.jar"); + } + + private static String getJavaHome() { + return System.getProperty("java.home"); + } + +} diff --git a/spring-boot-tools/spring-boot-loader-tools/src/test/java/org/springframework/boot/loader/tools/JvmUtilsTests.java b/spring-boot-tools/spring-boot-loader-tools/src/test/java/org/springframework/boot/loader/tools/JvmUtilsTests.java new file mode 100644 index 00000000000..690a70e4afb --- /dev/null +++ b/spring-boot-tools/spring-boot-loader-tools/src/test/java/org/springframework/boot/loader/tools/JvmUtilsTests.java @@ -0,0 +1,43 @@ +/* + * Copyright 2012-2014 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. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package org.springframework.boot.loader.tools; + +import java.io.File; +import java.net.URL; + +import org.junit.Test; + +import static org.hamcrest.Matchers.endsWith; +import static org.hamcrest.Matchers.equalTo; +import static org.junit.Assert.assertThat; + +/** + * Tests for {@link JvmUtils}. + * + * @author Phillip Webb + */ +public class JvmUtilsTests { + + @Test + public void getToolsJar() throws Exception { + URL jarUrl = JvmUtils.getToolsJarUrl(); + System.out.println(jarUrl); + assertThat(jarUrl.toString(), endsWith(".jar")); + assertThat(new File(jarUrl.toURI()).exists(), equalTo(true)); + } + +} diff --git a/spring-boot-tools/spring-boot-maven-plugin/pom.xml b/spring-boot-tools/spring-boot-maven-plugin/pom.xml index 2796c6af5fb..a8ec9898268 100644 --- a/spring-boot-tools/spring-boot-maven-plugin/pom.xml +++ b/spring-boot-tools/spring-boot-maven-plugin/pom.xml @@ -12,28 +12,6 @@ ${basedir}/../.. - - standard-jdk - - - ${java.home}/../lib/tools.jar - - - - ${java.home}/../lib/tools.jar - - - - apple-jdk - - - ${java.home}/../Classes/classes.jar - - - - ${java.home}/../Classes/classes.jar - - integration @@ -68,13 +46,6 @@ - - com.sun - tools - ${java.version} - system - ${tools-jar} - ${project.groupId} spring-boot-loader-tools