diff --git a/agent/src/main/java/com/taobao/arthas/agent3/AgentBootstrap.java b/agent/src/main/java/com/taobao/arthas/agent3/AgentBootstrap.java index 03ff15d13..347a35171 100755 --- a/agent/src/main/java/com/taobao/arthas/agent3/AgentBootstrap.java +++ b/agent/src/main/java/com/taobao/arthas/agent3/AgentBootstrap.java @@ -1,6 +1,5 @@ package com.taobao.arthas.agent3; -import java.arthas.Spy; import java.io.File; import java.io.FileOutputStream; import java.io.PrintStream; @@ -19,7 +18,6 @@ import com.taobao.arthas.agent.ArthasClassloader; * @author vlinux on 15/5/19. */ public class AgentBootstrap { - private static final String RESET = "resetArthasClassLoader"; private static final String ARTHAS_SPY_JAR = "arthas-spy.jar"; private static final String ARTHAS_CORE_JAR = "arthas-core.jar"; private static final String ARTHAS_BOOTSTRAP = "com.taobao.arthas.core.server.ArthasBootstrap"; @@ -79,7 +77,7 @@ public class AgentBootstrap { Class spyClass = null; if (parent != null) { try { - parent.loadClass("java.arthas.Spy"); + parent.loadClass("java.arthas.SpyAPI"); } catch (Throwable e) { // ignore } @@ -99,10 +97,6 @@ public class AgentBootstrap { return arthasClassLoader; } - private static void initSpy() throws NoSuchMethodException { - Spy.AGENT_RESET_METHOD = AgentBootstrap.class.getMethod(RESET); - } - private static synchronized void main(String args, final Instrumentation inst) { try { ps.println("Arthas server agent start..."); @@ -155,7 +149,6 @@ public class AgentBootstrap { * Use a dedicated thread to run the binding logic to prevent possible memory leak. #195 */ final ClassLoader agentLoader = getClassLoader(inst, spyJarFile, arthasCoreJarFile); - initSpy(); Thread bindingThread = new Thread() { @Override diff --git a/core/src/main/java/com/taobao/arthas/core/server/ArthasBootstrap.java b/core/src/main/java/com/taobao/arthas/core/server/ArthasBootstrap.java index 33d3a9ade..6fc3fa010 100644 --- a/core/src/main/java/com/taobao/arthas/core/server/ArthasBootstrap.java +++ b/core/src/main/java/com/taobao/arthas/core/server/ArthasBootstrap.java @@ -1,6 +1,6 @@ package com.taobao.arthas.core.server; -import java.arthas.Spy; +import java.arthas.SpyAPI; import java.io.File; import java.io.IOException; import java.lang.instrument.Instrumentation; @@ -26,7 +26,6 @@ import com.alibaba.arthas.deps.org.slf4j.LoggerFactory; import com.alibaba.arthas.tunnel.client.TunnelClient; import com.taobao.arthas.common.AnsiLog; import com.taobao.arthas.common.PidUtils; -import com.taobao.arthas.core.advisor.AdviceWeaver; import com.taobao.arthas.core.advisor.TransformerManager; import com.taobao.arthas.core.command.BuiltinCommandPack; import com.taobao.arthas.core.config.BinderUtils; @@ -44,7 +43,6 @@ import com.taobao.arthas.core.shell.impl.ShellServerImpl; import com.taobao.arthas.core.shell.term.impl.HttpTermServer; import com.taobao.arthas.core.shell.term.impl.httptelnet.HttpTelnetTermServer; import com.taobao.arthas.core.util.ArthasBanner; -import com.taobao.arthas.core.util.Constants; import com.taobao.arthas.core.util.FileUtils; import com.taobao.arthas.core.util.LogUtil; import com.taobao.arthas.core.util.UserStatUtil; @@ -121,18 +119,10 @@ public class ArthasBootstrap { Runtime.getRuntime().addShutdownHook(shutdown); } - private static void initSpy() throws ClassNotFoundException, NoSuchMethodException { - Class adviceWeaverClass = AdviceWeaver.class; - Method onBefore = adviceWeaverClass.getMethod(AdviceWeaver.ON_BEFORE, int.class, ClassLoader.class, String.class, - String.class, String.class, Object.class, Object[].class); - Method onReturn = adviceWeaverClass.getMethod(AdviceWeaver.ON_RETURN, Object.class); - Method onThrows = adviceWeaverClass.getMethod(AdviceWeaver.ON_THROWS, Throwable.class); - Method beforeInvoke = adviceWeaverClass.getMethod(AdviceWeaver.BEFORE_INVOKE, int.class, String.class, String.class, String.class, int.class); - Method afterInvoke = adviceWeaverClass.getMethod(AdviceWeaver.AFTER_INVOKE, int.class, String.class, String.class, String.class, int.class); - Method throwInvoke = adviceWeaverClass.getMethod(AdviceWeaver.THROW_INVOKE, int.class, String.class, String.class, String.class, int.class); - Spy.init(AdviceWeaver.class.getClassLoader(), onBefore, onReturn, onThrows, beforeInvoke, afterInvoke, throwInvoke); + private static void initSpy() { + // TODO init SpyImpl ? } - + private void initArthasEnvironment(String args) throws IOException { if (arthasEnvironment == null) { arthasEnvironment = new ArthasEnvironment(); @@ -377,18 +367,17 @@ public class ArthasBootstrap { } /** - * 清除spy中对classloader的引用,避免内存泄露 + * 清除SpyAPI里的引用 */ private void cleanUpSpyReference() { + SpyAPI.setNopSpy(); + // AgentBootstrap.resetArthasClassLoader(); try { - // 从ArthasClassLoader中加载Spy - Class spyClass = this.getClass().getClassLoader().loadClass(Constants.SPY_CLASSNAME); - Method agentDestroyMethod = spyClass.getMethod("destroy"); - agentDestroyMethod.invoke(null); - } catch (ClassNotFoundException e) { - logger().error("Spy load failed from ArthasClassLoader, which should not happen", e); - } catch (Exception e) { - logger().error("Spy destroy failed: ", e); + Class clazz = ClassLoader.getSystemClassLoader().loadClass("com.taobao.arthas.agent3.AgentBootstrap"); + Method method = clazz.getDeclaredMethod("resetArthasClassLoader"); + method.invoke(null); + } catch (Throwable e) { + e.printStackTrace(); } } diff --git a/core/src/main/java/com/taobao/arthas/core/util/Constants.java b/core/src/main/java/com/taobao/arthas/core/util/Constants.java index 5beb6b75e..6bac42c89 100644 --- a/core/src/main/java/com/taobao/arthas/core/util/Constants.java +++ b/core/src/main/java/com/taobao/arthas/core/util/Constants.java @@ -13,11 +13,6 @@ public class Constants { private Constants() { } - /** - * Spy的全类名 - */ - public static final String SPY_CLASSNAME = "java.arthas.Spy"; - /** * 中断提示 */ diff --git a/spy/src/main/java/java/arthas/Spy.java b/spy/src/main/java/java/arthas/Spy.java deleted file mode 100644 index b05620894..000000000 --- a/spy/src/main/java/java/arthas/Spy.java +++ /dev/null @@ -1,131 +0,0 @@ -package java.arthas; - -import java.lang.reflect.Method; - -/** - * 间谍类
- * 藏匿在各个ClassLoader中 - * Created by vlinux on 15/8/23. - */ -public class Spy { - public static final String ON_BEFORE = "methodOnBegin"; - public static final String ON_RETURN = "methodOnReturnEnd"; - public static final String ON_THROWS = "methodOnThrowingEnd"; - public static final String BEFORE_INVOKE = "methodOnInvokeBeforeTracing"; - public static final String AFTER_INVOKE = "methodOnInvokeAfterTracing"; - public static final String THROW_INVOKE = "methodOnInvokeThrowTracing"; - - // -- 各种Advice的钩子引用 -- - public static volatile Method ON_BEFORE_METHOD; - public static volatile Method ON_RETURN_METHOD; - public static volatile Method ON_THROWS_METHOD; - public static volatile Method BEFORE_INVOKING_METHOD; - public static volatile Method AFTER_INVOKING_METHOD; - public static volatile Method THROW_INVOKING_METHOD; - - /** - * arthas's classloader 引用 - */ - public static volatile ClassLoader CLASSLOADER; - - /** - * 代理重设方法 - */ - public static volatile Method AGENT_RESET_METHOD; - - /** - * 用于普通的间谍初始化 - */ - public static void init( - ClassLoader classLoader, - Method onBeforeMethod, - Method onReturnMethod, - Method onThrowsMethod, - Method beforeInvokingMethod, - Method afterInvokingMethod, - Method throwInvokingMethod) { - CLASSLOADER = classLoader; - ON_BEFORE_METHOD = onBeforeMethod; - ON_RETURN_METHOD = onReturnMethod; - ON_THROWS_METHOD = onThrowsMethod; - BEFORE_INVOKING_METHOD = beforeInvokingMethod; - AFTER_INVOKING_METHOD = afterInvokingMethod; - THROW_INVOKING_METHOD = throwInvokingMethod; - } - - /** - * Clean up the reference to com.taobao.arthas.agent.AgentLauncher$1 - * to avoid classloader leak. - */ - public static void destroy() { - initEmptySpy(); - // clear the reference to ArthasClassLoader in AgentLauncher - if (AGENT_RESET_METHOD != null) { - try { - AGENT_RESET_METHOD.invoke(null); - } catch (Exception e) { - e.printStackTrace(); - } - } - AGENT_RESET_METHOD = null; - } - - private static void initEmptySpy() { - try { - Class adviceWeaverClass = Spy.class; - Method onBefore = adviceWeaverClass.getMethod(Spy.ON_BEFORE, int.class, ClassLoader.class, String.class, - String.class, String.class, Object.class, Object[].class); - Method onReturn = adviceWeaverClass.getMethod(Spy.ON_RETURN, Object.class); - Method onThrows = adviceWeaverClass.getMethod(Spy.ON_THROWS, Throwable.class); - Method beforeInvoke = adviceWeaverClass.getMethod(Spy.BEFORE_INVOKE, int.class, String.class, String.class, - String.class, int.class); - Method afterInvoke = adviceWeaverClass.getMethod(Spy.AFTER_INVOKE, int.class, String.class, String.class, - String.class, int.class); - Method throwInvoke = adviceWeaverClass.getMethod(Spy.THROW_INVOKE, int.class, String.class, String.class, - String.class, int.class); - Spy.init(null, onBefore, onReturn, onThrows, beforeInvoke, afterInvoke, throwInvoke); - } catch (Exception e) { - } - } - - /** - * empty method - * - * @see com.taobao.arthas.core.advisor.AdviceWeaver#methodOnBegin(int, - * ClassLoader, String, String, String, Object, Object[]) - * @param adviceId - * @param loader - * @param className - * @param methodName - * @param methodDesc - * @param target - * @param args - */ - public static void methodOnBegin(int adviceId, ClassLoader loader, String className, String methodName, - String methodDesc, Object target, Object[] args) { - } - - /** - * empty method - * - * @see com.taobao.arthas.core.advisor.AdviceWeaver#methodOnReturnEnd(Object) - * @param returnObject - */ - public static void methodOnReturnEnd(Object returnObject) { - } - - public static void methodOnThrowingEnd(Throwable throwable) { - } - - public static void methodOnInvokeBeforeTracing(int adviceId, String owner, String name, String desc, - int lineNumber) { - } - - public static void methodOnInvokeAfterTracing(int adviceId, String owner, String name, String desc, - int lineNumber) { - } - - public static void methodOnInvokeThrowTracing(int adviceId, String owner, String name, String desc, - int lineNumber) { - } -} diff --git a/spy/src/main/java/java/arthas/SpyAPI.java b/spy/src/main/java/java/arthas/SpyAPI.java index 67d73adbd..5de04962b 100644 --- a/spy/src/main/java/java/arthas/SpyAPI.java +++ b/spy/src/main/java/java/arthas/SpyAPI.java @@ -21,7 +21,7 @@ package java.arthas; * */ public class SpyAPI { - + private static final AbstractSpy NOPSPY = new NopSpy(); private static volatile AbstractSpy spyInstance = new NopSpy(); public static AbstractSpy getSpy() { @@ -31,6 +31,10 @@ public class SpyAPI { public static void setSpy(AbstractSpy spy) { spyInstance = spy; } + + public static void setNopSpy() { + setSpy(NOPSPY); + } public static void atEnter(Class clazz, String methodInfo, Object target, Object[] args) { spyInstance.atEnter(clazz, methodInfo, target, args);