diff --git a/bin/sandbox.sh b/bin/sandbox.sh index 8f5b7216..f451672f 100755 --- a/bin/sandbox.sh +++ b/bin/sandbox.sh @@ -1,7 +1,7 @@ # program : sandbox # author : luanjia@taobao.com -# date : 2017-01-01 -# version : 0.0.0.1 +# date : 2018-03-12 +# version : 0.0.0.2 #!/usr/bin/env bash @@ -218,7 +218,7 @@ function attach_jvm() { -jar ${SANDBOX_LIB_DIR}/sandbox-core.jar \ ${TARGET_JVM_PID} \ "${SANDBOX_LIB_DIR}/sandbox-agent.jar" \ - "token=${token};ip=${TARGET_SERVER_IP};port=${TARGET_SERVER_PORT};namespace=${TARGET_NAMESPACE}" \ + "home=${SANDBOX_HOME_DIR};token=${token};ip=${TARGET_SERVER_IP};port=${TARGET_SERVER_PORT};namespace=${TARGET_NAMESPACE}" \ || exit_on_err 1 "attach JVM ${TARGET_JVM_PID} fail." # get network from attach result diff --git a/sandbox-agent/src/main/java/com/alibaba/jvm/sandbox/agent/AgentLauncher.java b/sandbox-agent/src/main/java/com/alibaba/jvm/sandbox/agent/AgentLauncher.java index a46f842b..e62f816b 100755 --- a/sandbox-agent/src/main/java/com/alibaba/jvm/sandbox/agent/AgentLauncher.java +++ b/sandbox-agent/src/main/java/com/alibaba/jvm/sandbox/agent/AgentLauncher.java @@ -10,43 +10,74 @@ import java.util.concurrent.ConcurrentHashMap; import java.util.jar.JarFile; +import static java.lang.String.format; + /** * SandboxAgent启动器 * Created by luanjia@taobao.com on 16/7/30. */ public class AgentLauncher { - // sandbox主目录 - private static final String SANDBOX_HOME - = new File(AgentLauncher.class.getProtectionDomain().getCodeSource().getLocation().getFile()) - .getParentFile().getParent(); +// // sandbox配置文件目录 +// private static final String SANDBOX_CFG_PATH +// = SANDBOX_HOME + File.separatorChar + "cfg"; +// +// // 模块目录 +// private static final String SANDBOX_MODULE_PATH +// = SANDBOX_HOME + File.separatorChar + "module"; +// +// +// // sandbox核心工程文件 +// private static final String SANDBOX_CORE_JAR_PATH +// = SANDBOX_HOME + File.separatorChar + "lib" + File.separator + "sandbox-core.jar"; +// +// // sandbox-spy工程文件 +// private static final String SANDBOX_SPY_JAR_PATH +// = SANDBOX_HOME + File.separatorChar + "lib" + File.separator + "sandbox-spy.jar"; +// +// private static final String SANDBOX_PROPERTIES_PATH +// = SANDBOX_CFG_PATH + File.separator + "sandbox.properties"; +// +// // sandbox-provider库目录 +// private static final String SANDBOX_PROVIDER_LIB_PATH +// = SANDBOX_HOME + File.separatorChar + "provider"; + + + private static String getSandboxCfgPath(String sandboxHome) { + return sandboxHome + File.separatorChar + "cfg"; + } + + private static String getSandboxModulePath(String sandboxHome) { + return sandboxHome + File.separatorChar + "module"; + } - // sandbox配置文件目录 - private static final String SANDBOX_CFG_PATH - = SANDBOX_HOME + File.separatorChar + "cfg"; + private static String getSandboxCoreJarPath(String sandboxHome) { + return sandboxHome + File.separatorChar + "lib" + File.separator + "sandbox-core.jar"; + } - // 模块目录 - private static final String SANDBOX_MODULE_PATH - = SANDBOX_HOME + File.separatorChar + "module"; + private static String getSandboxSpyJarPath(String sandboxHome) { + return getSandboxCfgPath(sandboxHome) + File.separatorChar + "lib" + File.separator + "sandbox-spy.jar"; + } - private static final String SANDBOX_USER_MODULE_PATH - = System.getProperties().getProperty("user.home") - + File.separator + ".sandbox-module"; + private static String getSandboxPropertiesPath(String sandboxHome) { + return sandboxHome + File.separator + "sandbox.properties"; + } - // sandbox核心工程文件 - private static final String SANDBOX_CORE_JAR_PATH - = SANDBOX_HOME + File.separatorChar + "lib" + File.separator + "sandbox-core.jar"; + private static String getSandboxProviderPath(String sandboxHome) { + return sandboxHome + File.separatorChar + "provider"; + } - // sandbox-spy工程文件 - private static final String SANDBOX_SPY_JAR_PATH - = SANDBOX_HOME + File.separatorChar + "lib" + File.separator + "sandbox-spy.jar"; - private static final String SANDBOX_PROPERTIES_PATH - = SANDBOX_CFG_PATH + File.separator + "sandbox.properties"; + // sandbox默认主目录 + private static final String SANDBOX_HOME + = new File(AgentLauncher.class.getProtectionDomain().getCodeSource().getLocation().getFile()) + .getParentFile() + .getParent(); + private static final String DEFAULT_SANDBOX_HOME = SANDBOX_HOME; - // sandbox-provider库目录 - private static final String SANDBOX_PROVIDER_LIB_PATH - = SANDBOX_HOME + File.separatorChar + "provider"; + private static final String SANDBOX_USER_MODULE_PATH + = System.getProperties().getProperty("user.home") + + File.separator + ".sandbox-module"; // 启动模式: agent方式加载 private static final String LAUNCH_MODE_AGENT = "agent"; @@ -122,7 +153,7 @@ private static synchronized void writeAttachResult(final String namespace, try { fw = new FileWriter(file, true); fw.append( - String.format("%s;%s;%s;%s\n", + format("%s;%s;%s;%s\n", namespace, token, local.getHostName(), @@ -167,21 +198,29 @@ private static synchronized ClassLoader loadOrDefineClassLoader(final String nam /** * 获取当前命名空间下的ClassLoader + *

+ * 该方法将会被{@code ControlModule#shutdown}通过反射调用, + * 请保持方法声明一致 * * @param namespace 命名空间 * @return 当前的ClassLoader * @since {@code sandbox-api:1.0.15} */ + @SuppressWarnings("unused") public static ClassLoader getClassLoader(final String namespace) { return sandboxClassLoaderMap.get(namespace); } /** * 清理namespace所指定的ClassLoader + *

+ * 该方法将会被{@code ControlModule#shutdown}通过反射调用, + * 请保持方法声明一致 * * @param namespace 命名空间 * @return 被清理的ClassLoader */ + @SuppressWarnings("unused") public static synchronized ClassLoader cleanClassLoader(final String namespace) { final SandboxClassLoader sandboxClassLoader = sandboxClassLoaderMap.remove(namespace); if (null != sandboxClassLoader) { @@ -200,10 +239,17 @@ private static synchronized InetSocketAddress main(final Map fea try { // 将Spy注入到BootstrapClassLoader - inst.appendToBootstrapClassLoaderSearch(new JarFile(new File(SANDBOX_SPY_JAR_PATH))); + inst.appendToBootstrapClassLoaderSearch(new JarFile(new File( + getSandboxSpyJarPath(getSandboxHome(featureMap)) + // SANDBOX_SPY_JAR_PATH + ))); // 构造自定义的类加载器,尽量减少Sandbox对现有工程的侵蚀 - final ClassLoader agentLoader = loadOrDefineClassLoader(namespace, SANDBOX_CORE_JAR_PATH); + final ClassLoader agentLoader = loadOrDefineClassLoader( + namespace, + getSandboxCoreJarPath(getSandboxHome(featureMap)) + // SANDBOX_CORE_JAR_PATH + ); // CoreConfigure类定义 final Class classOfConfigure = agentLoader.loadClass(CLASS_OF_CORE_CONFIGURE); @@ -254,6 +300,8 @@ private static synchronized InetSocketAddress main(final Map fea private static final String EMPTY_STRING = ""; + private static final String KEY_SANDBOX_HOME = "home"; + private static final String KEY_NAMESPACE = "namespace"; private static final String DEFAULT_NAMESPACE = "default"; @@ -294,8 +342,7 @@ private static Map toFeatureMap(final String featureString) { // KV对片段数组 final String[] kvPairSegmentArray = featureString.split(";"); - if (null == kvPairSegmentArray - || kvPairSegmentArray.length <= 0) { + if (kvPairSegmentArray.length <= 0) { return featureMap; } @@ -304,8 +351,7 @@ private static Map toFeatureMap(final String featureString) { continue; } final String[] kvSegmentArray = kvPairSegmentString.split("="); - if (null == kvSegmentArray - || kvSegmentArray.length != 2 + if (kvSegmentArray.length != 2 || isBlankString(kvSegmentArray[0]) || isBlankString(kvSegmentArray[1])) { continue; @@ -323,6 +369,11 @@ private static String getDefault(final Map map, final String key : defaultValue; } + // 获取主目录 + private static String getSandboxHome(final Map featureMap) { + return getDefault(featureMap, KEY_SANDBOX_HOME, DEFAULT_SANDBOX_HOME); + } + // 获取命名空间 private static String getNamespace(final Map featureMap) { return getDefault(featureMap, KEY_NAMESPACE, DEFAULT_NAMESPACE); @@ -335,7 +386,12 @@ private static String getToken(final Map featureMap) { // 获取容器配置文件路径 private static String getPropertiesFilePath(final Map featureMap) { - return getDefault(featureMap, KEY_PROPERTIES_FILE_PATH, SANDBOX_PROPERTIES_PATH); + return getDefault( + featureMap, + KEY_PROPERTIES_FILE_PATH, + getSandboxPropertiesPath(getSandboxHome(featureMap)) + // SANDBOX_PROPERTIES_PATH + ); } // 如果featureMap中有对应的key值,则将featureMap中的[K,V]对合并到featureSB中 @@ -344,21 +400,26 @@ private static void appendFromFeatureMap(final StringBuilder featureSB, final String key, final String defaultValue) { if (featureMap.containsKey(key)) { - featureSB.append(String.format("%s=%s;", key, getDefault(featureMap, key, defaultValue))); + featureSB.append(format("%s=%s;", key, getDefault(featureMap, key, defaultValue))); } } // 将featureMap中的[K,V]对转换为featureString private static String toFeatureString(final Map featureMap) { + final String sandboxHome = getSandboxHome(featureMap); final StringBuilder featureSB = new StringBuilder( - String.format( + format( ";cfg=%s;system_module=%s;mode=%s;sandbox_home=%s;user_module=%s;provider=%s;namespace=%s;", - SANDBOX_CFG_PATH, - SANDBOX_MODULE_PATH, + getSandboxCfgPath(sandboxHome), + // SANDBOX_CFG_PATH, + getSandboxModulePath(sandboxHome), + // SANDBOX_MODULE_PATH, LAUNCH_MODE, - SANDBOX_HOME, + sandboxHome, + // SANDBOX_HOME, SANDBOX_USER_MODULE_PATH, - SANDBOX_PROVIDER_LIB_PATH, + getSandboxProviderPath(sandboxHome), + // SANDBOX_PROVIDER_LIB_PATH, getNamespace(featureMap) ) ); diff --git a/sandbox-agent/src/main/java/com/alibaba/jvm/sandbox/agent/SandboxClassLoader.java b/sandbox-agent/src/main/java/com/alibaba/jvm/sandbox/agent/SandboxClassLoader.java index e91c4f50..d5fe18ed 100755 --- a/sandbox-agent/src/main/java/com/alibaba/jvm/sandbox/agent/SandboxClassLoader.java +++ b/sandbox-agent/src/main/java/com/alibaba/jvm/sandbox/agent/SandboxClassLoader.java @@ -53,6 +53,18 @@ public String toString() { } + /** + * 尽可能关闭ClassLoader + *

+ * URLClassLoader会打开指定的URL资源,在SANDBOX中则是对应的Jar文件,如果不在shutdown的时候关闭ClassLoader,会导致下次再次加载 + * 的时候,依然会访问到上次所打开的文件(底层被缓存起来了) + *

+ * 在JDK1.7版本中,URLClassLoader提供了{@code close()}方法来完成这件事;但在JDK1.6版本就要下点手段了; + *

+ * 该方法将会被{@code ControlModule#shutdown}通过反射调用, + * 请保持方法声明一致 + */ + @SuppressWarnings("unused") public void closeIfPossible() { // 如果是JDK7+的版本, URLClassLoader实现了Closeable接口,直接调用即可