Commit 5d7c4150 authored by shengnan hu's avatar shengnan hu
Browse files

init

parents
Pipeline #4715 failed with stage
in 30 seconds
<?xml version="1.0"?>
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd">
<modelVersion>4.0.0</modelVersion>
<parent>
<groupId>com.taobao.arthas</groupId>
<artifactId>arthas-all</artifactId>
<version>${revision}</version>
<relativePath>../pom.xml</relativePath>
</parent>
<artifactId>arthas-core</artifactId>
<name>arthas-core</name>
<properties>
<arthas.deps.package>com.alibaba.arthas.deps</arthas.deps.package>
</properties>
<build>
<finalName>arthas-core</finalName>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.6</source>
<target>1.6</target>
<encoding>UTF-8</encoding>
<showDeprecation>true</showDeprecation>
</configuration>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-shade-plugin</artifactId>
<version>3.2.3</version>
<executions>
<execution>
<phase>package</phase>
<goals>
<goal>shade</goal>
</goals>
<configuration>
<finalName>arthas-core-shade</finalName>
<transformers>
<transformer implementation="org.apache.maven.plugins.shade.resource.ManifestResourceTransformer">
<mainClass>com.taobao.arthas.core.Arthas</mainClass>
<manifestEntries>
<Created-By>core engine team, middleware group, alibaba inc.</Created-By>
<Implementation-Version>${project.version}</Implementation-Version>
<Implementation-Vendor-Id>com.taobao.arthas</Implementation-Vendor-Id>
<Specification-Version>${project.version}</Specification-Version>
<Specification-Title>arthas-core</Specification-Title>
</manifestEntries>
</transformer>
</transformers>
<relocations>
<!-- https://github.com/hengyunabc/arthas-repackage-deps -->
<relocation>
<pattern>org.slf4j</pattern>
<shadedPattern>${arthas.deps.package}.org.slf4j</shadedPattern>
</relocation>
<relocation>
<pattern>ch.qos.logback</pattern>
<shadedPattern>${arthas.deps.package}.ch.qos.logback</shadedPattern>
</relocation>
<relocation>
<pattern>io.netty</pattern>
<shadedPattern>${arthas.deps.package}.io.netty</shadedPattern>
</relocation>
<relocation>
<pattern>com.alibaba.fastjson</pattern>
<shadedPattern>${arthas.deps.package}.com.alibaba.fastjson</shadedPattern>
</relocation>
</relocations>
<filters>
<filter>
<artifact>com.alibaba.middleware:termd-core</artifact>
<excludes>
<exclude>io/termd/core/http/*.js</exclude>
<exclude>io/termd/core/http/*.css</exclude>
<exclude>io/termd/core/http/*.html</exclude>
<exclude>io/termd/core/http/*.png</exclude>
</excludes>
</filter>
</filters>
</configuration>
</execution>
</executions>
</plugin>
<!-- 把原来的logger command相关类还原,因为被shade plugin relocation修改了package -->
<plugin>
<artifactId>maven-antrun-plugin</artifactId>
<executions>
<execution>
<phase>package</phase>
<configuration>
<tasks>
<unzip src="${project.build.directory}/${project.build.finalName}-shade.${project.packaging}" dest="${project.build.directory}/tmp_out" />
<copy overwrite="true" todir="${project.build.directory}/tmp_out/com/taobao/arthas/core/command/logger">
<fileset dir="${project.build.directory}/classes/com/taobao/arthas/core/command/logger" />
</copy>
<zip basedir="${project.build.directory}/tmp_out" destfile="${project.build.directory}/${project.build.finalName}-shade.${project.packaging}" />
</tasks>
</configuration>
<goals>
<goal>run</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
<dependencies>
<dependency>
<groupId>com.taobao.arthas</groupId>
<artifactId>arthas-spy</artifactId>
<version>${project.version}</version>
<scope>provided</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>com.taobao.arthas</groupId>
<artifactId>arthas-common</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>com.taobao.arthas</groupId>
<artifactId>arthas-vmtool</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>bytekit-core</artifactId>
</dependency>
<dependency>
<groupId>net.bytebuddy</groupId>
<artifactId>byte-buddy-agent</artifactId>
<scope>provided</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>com.taobao.arthas</groupId>
<artifactId>arthas-memorycompiler</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>com.taobao.arthas</groupId>
<artifactId>arthas-tunnel-client</artifactId>
<version>${project.version}</version>
</dependency>
<dependency>
<groupId>com.alibaba.middleware</groupId>
<artifactId>termd-core</artifactId>
</dependency>
<dependency>
<groupId>com.alibaba.middleware</groupId>
<artifactId>cli</artifactId>
</dependency>
<dependency>
<groupId>com.taobao.text</groupId>
<artifactId>text-ui</artifactId>
</dependency>
<dependency>
<groupId>com.fifesoft</groupId>
<artifactId>rsyntaxtextarea</artifactId>
</dependency>
<!--<dependency>-->
<!--<groupId>org.codehaus.groovy</groupId>-->
<!--<artifactId>groovy-all</artifactId>-->
<!--</dependency>-->
<!-- slf4j-api/logback-classic/logback-core 不能打包到应用里,因为真正使用的是 arthas-repackage-deps -->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
<scope>provided</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<scope>provided</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-core</artifactId>
<scope>provided</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>com.alibaba.arthas</groupId>
<artifactId>arthas-repackage-logger</artifactId>
</dependency>
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
<scope>provided</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.apache.logging.log4j</groupId>
<artifactId>log4j-core</artifactId>
<version>2.12.4</version>
<scope>provided</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>com.alibaba</groupId>
<artifactId>fastjson</artifactId>
</dependency>
<dependency>
<groupId>ognl</groupId>
<artifactId>ognl</artifactId>
</dependency>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.assertj</groupId>
<artifactId>assertj-core</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.mockito</groupId>
<artifactId>mockito-core</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>com.taobao.arthas</groupId>
<artifactId>math-game</artifactId>
<version>${project.version}</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.zeroturnaround</groupId>
<artifactId>zt-zip</artifactId>
<scope>test</scope>
</dependency>
<dependency>
<groupId>org.jboss.modules</groupId>
<artifactId>jboss-modules</artifactId>
<version>1.11.0.Final</version>
<scope>test</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.benf</groupId>
<artifactId>cfr</artifactId>
</dependency>
<!-- for com.sun.tools.attach.VirtualMachine api -->
<dependency>
<groupId>com.github.olivergondza</groupId>
<artifactId>maven-jdk-tools-wrapper</artifactId>
<version>0.1</version>
<scope>provided</scope>
<optional>true</optional>
</dependency>
</dependencies>
</project>
#arthas.config.overrideAll=true
arthas.telnetPort=3658
arthas.httpPort=8563
arthas.ip=127.0.0.1
# seconds
arthas.sessionTimeout=1800
#arthas.enhanceLoaders=java.lang.ClassLoader
# https://arthas.aliyun.com/doc/en/auth
# arthas.username=arthas
# arthas.password=arthas
# local connection non auth, like telnet 127.0.0.1 3658
arthas.localConnectionNonAuth=true
#arthas.appName=demoapp
#arthas.tunnelServer=ws://127.0.0.1:7777/ws
#arthas.agentId=mmmmmmyiddddd
#arthas.disabledCommands=stop,dump
#arthas.outputPath=arthas-output
\ No newline at end of file
package com.taobao.arthas.core;
import java.io.IOException;
import java.io.UnsupportedEncodingException;
import java.net.URLEncoder;
import java.util.Arrays;
import java.util.Properties;
import com.sun.tools.attach.VirtualMachine;
import com.sun.tools.attach.VirtualMachineDescriptor;
import com.taobao.arthas.common.AnsiLog;
import com.taobao.arthas.common.ArthasConstants;
import com.taobao.arthas.common.JavaVersionUtils;
import com.taobao.arthas.core.config.Configure;
import com.taobao.middleware.cli.CLI;
import com.taobao.middleware.cli.CLIs;
import com.taobao.middleware.cli.CommandLine;
import com.taobao.middleware.cli.Option;
import com.taobao.middleware.cli.TypedOption;
/**
* Arthas启动器
*/
public class Arthas {
int abaddddac;
private Arthas(String[] args) throws Exception {
attachAgent(parse(args));
}
private Configure parse(String[] args) {
Option pid = new TypedOption<Long>().setType(Long.class).setShortName("pid").setRequired(true);
Option core = new TypedOption<String>().setType(String.class).setShortName("core").setRequired(true);
Option agent = new TypedOption<String>().setType(String.class).setShortName("agent").setRequired(true);
Option target = new TypedOption<String>().setType(String.class).setShortName("target-ip");
Option telnetPort = new TypedOption<Integer>().setType(Integer.class)
.setShortName("telnet-port");
Option httpPort = new TypedOption<Integer>().setType(Integer.class)
.setShortName("http-port");
Option sessionTimeout = new TypedOption<Integer>().setType(Integer.class)
.setShortName("session-timeout");
Option username = new TypedOption<String>().setType(String.class).setShortName("username");
Option password = new TypedOption<String>().setType(String.class).setShortName("password");
Option tunnelServer = new TypedOption<String>().setType(String.class).setShortName("tunnel-server");
Option agentId = new TypedOption<String>().setType(String.class).setShortName("agent-id");
Option appName = new TypedOption<String>().setType(String.class).setShortName(ArthasConstants.APP_NAME);
Option statUrl = new TypedOption<String>().setType(String.class).setShortName("stat-url");
Option disabledCommands = new TypedOption<String>().setType(String.class).setShortName("disabled-commands");
CLI cli = CLIs.create("arthas").addOption(pid).addOption(core).addOption(agent).addOption(target)
.addOption(telnetPort).addOption(httpPort).addOption(sessionTimeout)
.addOption(username).addOption(password)
.addOption(tunnelServer).addOption(agentId).addOption(appName).addOption(statUrl).addOption(disabledCommands);
CommandLine commandLine = cli.parse(Arrays.asList(args));
Configure configure = new Configure();
configure.setJavaPid((Long) commandLine.getOptionValue("pid"));
configure.setArthasAgent((String) commandLine.getOptionValue("agent"));
configure.setArthasCore((String) commandLine.getOptionValue("core"));
if (commandLine.getOptionValue("session-timeout") != null) {
configure.setSessionTimeout((Integer) commandLine.getOptionValue("session-timeout"));
}
if (commandLine.getOptionValue("target-ip") != null) {
configure.setIp((String) commandLine.getOptionValue("target-ip"));
}
if (commandLine.getOptionValue("telnet-port") != null) {
configure.setTelnetPort((Integer) commandLine.getOptionValue("telnet-port"));
}
if (commandLine.getOptionValue("http-port") != null) {
configure.setHttpPort((Integer) commandLine.getOptionValue("http-port"));
}
configure.setUsername((String) commandLine.getOptionValue("username"));
configure.setPassword((String) commandLine.getOptionValue("password"));
configure.setTunnelServer((String) commandLine.getOptionValue("tunnel-server"));
configure.setAgentId((String) commandLine.getOptionValue("agent-id"));
configure.setStatUrl((String) commandLine.getOptionValue("stat-url"));
configure.setDisabledCommands((String) commandLine.getOptionValue("disabled-commands"));
configure.setAppName((String) commandLine.getOptionValue(ArthasConstants.APP_NAME));
return configure;
}
private void attachAgent(Configure configure) throws Exception {
VirtualMachineDescriptor virtualMachineDescriptor = null;
for (VirtualMachineDescriptor descriptor : VirtualMachine.list()) {
String pid = descriptor.id();
if (pid.equals(Long.toString(configure.getJavaPid()))) {
virtualMachineDescriptor = descriptor;
break;
}
}
VirtualMachine virtualMachine = null;
try {
if (null == virtualMachineDescriptor) { // 使用 attach(String pid) 这种方式
virtualMachine = VirtualMachine.attach("" + configure.getJavaPid());
} else {
virtualMachine = VirtualMachine.attach(virtualMachineDescriptor);
}
Properties targetSystemProperties = virtualMachine.getSystemProperties();
String targetJavaVersion = JavaVersionUtils.javaVersionStr(targetSystemProperties);
String currentJavaVersion = JavaVersionUtils.javaVersionStr();
if (targetJavaVersion != null && currentJavaVersion != null) {
if (!targetJavaVersion.equals(currentJavaVersion)) {
AnsiLog.warn("Current VM java version: {} do not match target VM java version: {}, attach may fail.",
currentJavaVersion, targetJavaVersion);
AnsiLog.warn("Target VM JAVA_HOME is {}, arthas-boot JAVA_HOME is {}, try to set the same JAVA_HOME.",
targetSystemProperties.getProperty("java.home"), System.getProperty("java.home"));
}
}
String arthasAgentPath = configure.getArthasAgent();
//convert jar path to unicode string
configure.setArthasAgent(encodeArg(arthasAgentPath));
configure.setArthasCore(encodeArg(configure.getArthasCore()));
try {
virtualMachine.loadAgent(arthasAgentPath,
configure.getArthasCore() + ";" + configure.toString());
} catch (IOException e) {
if (e.getMessage() != null && e.getMessage().contains("Non-numeric value found")) {
AnsiLog.warn(e);
AnsiLog.warn("It seems to use the lower version of JDK to attach the higher version of JDK.");
AnsiLog.warn(
"This error message can be ignored, the attach may have been successful, and it will still try to connect.");
} else {
throw e;
}
}
} finally {
if (null != virtualMachine) {
virtualMachine.detach();
}
}
}
private static String encodeArg(String arg) {
try {
return URLEncoder.encode(arg, "utf-8");
} catch (UnsupportedEncodingException e) {
return arg;
}
}
public static void main(String[] args) {
try {
new Arthas(args);
} catch (Throwable t) {
AnsiLog.error("Start arthas failed, exception stack trace: ");
t.printStackTrace();
System.exit(-1);
}
}
}
package com.taobao.arthas.core;
import com.taobao.arthas.common.JavaVersionUtils;
/**
* 全局开关
* Created by vlinux on 15/6/4.
*/
public class GlobalOptions {
public static final String STRICT_MESSAGE = "By default, strict mode is true, "
+ "not allowed to set object properties. "
+ "Want to set object properties, execute `options strict false`";
int bcsssadddd;
/**
* 是否支持系统类<br/>
* 这个开关打开之后将能代理到来自JVM的部分类,由于有非常强的安全风险可能会引起系统崩溃<br/>
* 所以这个开关默认是关闭的,除非你非常了解你要做什么,否则请不要打开
*/
@Option(level = 0,
name = "unsafe",
summary = "Option to support system-level class",
description =
"This option enables to proxy functionality of JVM classes."
+ " Due to serious security risk a JVM crash is possibly be introduced."
+ " Do not activate it unless you are able to manage."
)
public static volatile boolean isUnsafe = false;
/**
* 是否支持dump被增强的类<br/>
* 这个开关打开这后,每次增强类的时候都将会将增强的类dump到文件中,以便于进行反编译分析
*/
@Option(level = 1,
name = "dump",
summary = "Option to dump the enhanced classes",
description =
"This option enables the enhanced classes to be dumped to external file " +
"for further de-compilation and analysis."
)
public static volatile boolean isDump = false;
/**
* 是否支持批量增强<br/>
* 这个开关打开后,每次均是批量增强类
*/
@Option(level = 1,
name = "batch-re-transform",
summary = "Option to support batch reTransform Class",
description = "This options enables to reTransform classes with batch mode."
)
public static volatile boolean isBatchReTransform = true;
/**
* 是否支持json格式化输出<br/>
* 这个开关打开后,使用json格式输出目标对象,配合-x参数使用
*/
@Option(level = 2,
name = "json-format",
summary = "Option to support JSON format of object output",
description = "This option enables to format object output with JSON when -x option selected."
)
public static volatile boolean isUsingJson = false;
/**
* 是否关闭子类
*/
@Option(
level = 1,
name = "disable-sub-class",
summary = "Option to control include sub class when class matching",
description = "This option disable to include sub class when matching class."
)
public static volatile boolean isDisableSubClass = false;
/**
* 是否在interface类里搜索函数
* https://github.com/alibaba/arthas/issues/1105
*/
@Option(
level = 1,
name = "support-default-method",
summary = "Option to control include default method in interface when class matching",
description = "This option disable to include default method in interface when matching class."
)
public static volatile boolean isSupportDefaultMethod = JavaVersionUtils.isGreaterThanJava7();
/**
* 是否日志中保存命令执行结果
*/
@Option(level = 1,
name = "save-result",
summary = "Option to print command's result to log file",
description = "This option enables to save each command's result to log file, " +
"which path is ${user.home}/logs/arthas-cache/result.log."
)
public static volatile boolean isSaveResult = false;
/**
* job的超时时间
*/
@Option(level = 2,
name = "job-timeout",
summary = "Option to job timeout",
description = "This option setting job timeout,The unit can be d, h, m, s for day, hour, minute, second. "
+ "1d is one day in default"
)
public static volatile String jobTimeout = "1d";
/**
* 是否打印parent类里的field
* @see com.taobao.arthas.core.view.ObjectView
*/
@Option(level = 1,
name = "print-parent-fields",
summary = "Option to print all fileds in parent class",
description = "This option enables print files in parent class, default value true."
)
public static volatile boolean printParentFields = true;
/**
* 是否打开verbose 开关
*/
@Option(level = 1,
name = "verbose",
summary = "Option to print verbose information",
description = "This option enables print verbose information, default value false."
)
public static volatile boolean verbose = false;
/**
* 是否打开strict 开关
*/
@Option(level = 1,
name = "strict",
summary = "Option to strict mode",
description = STRICT_MESSAGE
)
public static volatile boolean strict = true;
}
package com.taobao.arthas.core;
import java.lang.annotation.ElementType;
import java.lang.annotation.Retention;
import java.lang.annotation.RetentionPolicy;
import java.lang.annotation.Target;
/**
* Arthas全局选项
*/
@Retention(RetentionPolicy.RUNTIME)
@Target(ElementType.FIELD)
public @interface Option {
/*
* 选项级别,数字越小级别越高
*/
int level();
/*
* 选项名称
*/
String name();
/*
* 选项摘要说明
*/
String summary();
/*
* 命令描述
*/
String description();
}
\ No newline at end of file
package com.taobao.arthas.core.advisor;
public enum AccessPoint {
ACCESS_BEFORE(1, "AtEnter"), ACCESS_AFTER_RETUNING(1 << 1, "AtExit"), ACCESS_AFTER_THROWING(1 << 2, "AtExceptionExit");
private int value;
private String key;
public int getValue() {
return value;
}
public String getKey() {
return key;
}
AccessPoint(int value, String key) {
this.value = value;
this.key = key;
}
}
\ No newline at end of file
package com.taobao.arthas.core.advisor;
/**
* 通知点 Created by vlinux on 15/5/20.
*/
public class Advice {
private final ClassLoader loader;
private final Class<?> clazz;
private final ArthasMethod method;
private final Object target;
private final Object[] params;
private final Object returnObj;
private final Throwable throwExp;
private final boolean isBefore;
private final boolean isThrow;
private final boolean isReturn;
public boolean isBefore() {
return isBefore;
}
public boolean isAfterReturning() {
return isReturn;
}
public boolean isAfterThrowing() {
return isThrow;
}
public ClassLoader getLoader() {
return loader;
}
public Object getTarget() {
return target;
}
public Object[] getParams() {
return params;
}
public Object getReturnObj() {
return returnObj;
}
public Throwable getThrowExp() {
return throwExp;
}
public Class<?> getClazz() {
return clazz;
}
public ArthasMethod getMethod() {
return method;
}
/**
* for finish
*
* @param loader 类加载器
* @param clazz 类
* @param method 方法
* @param target 目标类
* @param params 调用参数
* @param returnObj 返回值
* @param throwExp 抛出异常
* @param access 进入场景
*/
private Advice(
ClassLoader loader,
Class<?> clazz,
ArthasMethod method,
Object target,
Object[] params,
Object returnObj,
Throwable throwExp,
int access) {
this.loader = loader;
this.clazz = clazz;
this.method = method;
this.target = target;
this.params = params;
this.returnObj = returnObj;
this.throwExp = throwExp;
isBefore = (access & AccessPoint.ACCESS_BEFORE.getValue()) == AccessPoint.ACCESS_BEFORE.getValue();
isThrow = (access & AccessPoint.ACCESS_AFTER_THROWING.getValue()) == AccessPoint.ACCESS_AFTER_THROWING.getValue();
isReturn = (access & AccessPoint.ACCESS_AFTER_RETUNING.getValue()) == AccessPoint.ACCESS_AFTER_RETUNING.getValue();
}
public static Advice newForBefore(ClassLoader loader,
Class<?> clazz,
ArthasMethod method,
Object target,
Object[] params) {
return new Advice(
loader,
clazz,
method,
target,
params,
null, //returnObj
null, //throwExp
AccessPoint.ACCESS_BEFORE.getValue()
);
}
public static Advice newForAfterReturning(ClassLoader loader,
Class<?> clazz,
ArthasMethod method,
Object target,
Object[] params,
Object returnObj) {
return new Advice(
loader,
clazz,
method,
target,
params,
returnObj,
null, //throwExp
AccessPoint.ACCESS_AFTER_RETUNING.getValue()
);
}
public static Advice newForAfterThrowing(ClassLoader loader,
Class<?> clazz,
ArthasMethod method,
Object target,
Object[] params,
Throwable throwExp) {
return new Advice(
loader,
clazz,
method,
target,
params,
null, //returnObj
throwExp,
AccessPoint.ACCESS_AFTER_THROWING.getValue()
);
}
}
package com.taobao.arthas.core.advisor;
/**
* 通知监听器<br/>
* Created by vlinux on 15/5/17.
*/
public interface AdviceListener {
long id();
/**
* 监听器创建<br/>
* 监听器被注册时触发
*/
void create();
/**
* 监听器销毁<br/>
* 监听器被销毁时触发
*/
void destroy();
/**
* 前置通知
*
* @param clazz 类
* @param methodName 方法名
* @param methodDesc 方法描述
* @param target 目标类实例
* 若目标为静态方法,则为null
* @param args 参数列表
* @throws Throwable 通知过程出错
*/
void before(
Class<?> clazz, String methodName, String methodDesc,
Object target, Object[] args) throws Throwable;
/**
* 返回通知
*
* @param clazz 类
* @param methodName 方法名
* @param methodDesc 方法描述
* @param target 目标类实例
* 若目标为静态方法,则为null
* @param args 参数列表
* @param returnObject 返回结果
* 若为无返回值方法(void),则为null
* @throws Throwable 通知过程出错
*/
void afterReturning(
Class<?> clazz, String methodName, String methodDesc,
Object target, Object[] args,
Object returnObject) throws Throwable;
/**
* 异常通知
*
* @param clazz 类
* @param methodName 方法名
* @param methodDesc 方法描述
* @param target 目标类实例
* 若目标为静态方法,则为null
* @param args 参数列表
* @param throwable 目标异常
* @throws Throwable 通知过程出错
*/
void afterThrowing(
Class<?> clazz, String methodName, String methodDesc,
Object target, Object[] args,
Throwable throwable) throws Throwable;
}
package com.taobao.arthas.core.advisor;
import java.util.concurrent.atomic.AtomicLong;
import com.taobao.arthas.core.command.express.ExpressException;
import com.taobao.arthas.core.command.express.ExpressFactory;
import com.taobao.arthas.core.shell.command.CommandProcess;
import com.taobao.arthas.core.shell.system.Process;
import com.taobao.arthas.core.shell.system.ProcessAware;
import com.taobao.arthas.core.util.Constants;
import com.taobao.arthas.core.util.StringUtils;
/**
*
* @author hengyunabc 2020-05-20
*
*/
public abstract class AdviceListenerAdapter implements AdviceListener, ProcessAware {
private static final AtomicLong ID_GENERATOR = new AtomicLong(0);
private Process process;
private long id = ID_GENERATOR.addAndGet(1);
private boolean verbose;
@Override
public long id() {
return id;
}
@Override
public void create() {
// default no-op
}
@Override
public void destroy() {
// default no-op
}
public Process getProcess() {
return process;
}
public void setProcess(Process process) {
this.process = process;
}
@Override
final public void before(Class<?> clazz, String methodName, String methodDesc, Object target, Object[] args)
throws Throwable {
before(clazz.getClassLoader(), clazz, new ArthasMethod(clazz, methodName, methodDesc), target, args);
}
@Override
final public void afterReturning(Class<?> clazz, String methodName, String methodDesc, Object target, Object[] args,
Object returnObject) throws Throwable {
afterReturning(clazz.getClassLoader(), clazz, new ArthasMethod(clazz, methodName, methodDesc), target, args,
returnObject);
}
@Override
final public void afterThrowing(Class<?> clazz, String methodName, String methodDesc, Object target, Object[] args,
Throwable throwable) throws Throwable {
afterThrowing(clazz.getClassLoader(), clazz, new ArthasMethod(clazz, methodName, methodDesc), target, args,
throwable);
}
/**
* 前置通知
*
* @param loader 类加载器
* @param clazz 类
* @param method 方法
* @param target 目标类实例 若目标为静态方法,则为null
* @param args 参数列表
* @throws Throwable 通知过程出错
*/
public abstract void before(ClassLoader loader, Class<?> clazz, ArthasMethod method, Object target, Object[] args)
throws Throwable;
/**
* 返回通知
*
* @param loader 类加载器
* @param clazz 类
* @param method 方法
* @param target 目标类实例 若目标为静态方法,则为null
* @param args 参数列表
* @param returnObject 返回结果 若为无返回值方法(void),则为null
* @throws Throwable 通知过程出错
*/
public abstract void afterReturning(ClassLoader loader, Class<?> clazz, ArthasMethod method, Object target,
Object[] args, Object returnObject) throws Throwable;
/**
* 异常通知
*
* @param loader 类加载器
* @param clazz 类
* @param method 方法
* @param target 目标类实例 若目标为静态方法,则为null
* @param args 参数列表
* @param throwable 目标异常
* @throws Throwable 通知过程出错
*/
public abstract void afterThrowing(ClassLoader loader, Class<?> clazz, ArthasMethod method, Object target,
Object[] args, Throwable throwable) throws Throwable;
/**
* 判断条件是否满足,满足的情况下需要输出结果
*
* @param conditionExpress 条件表达式
* @param advice 当前的advice对象
* @param cost 本次执行的耗时
* @return true 如果条件表达式满足
*/
protected boolean isConditionMet(String conditionExpress, Advice advice, double cost) throws ExpressException {
return StringUtils.isEmpty(conditionExpress)
|| ExpressFactory.threadLocalExpress(advice).bind(Constants.COST_VARIABLE, cost).is(conditionExpress);
}
protected Object getExpressionResult(String express, Advice advice, double cost) throws ExpressException {
return ExpressFactory.threadLocalExpress(advice).bind(Constants.COST_VARIABLE, cost).get(express);
}
/**
* 是否超过了上限,超过之后,停止输出
*
* @param limit 命令执行上限
* @param currentTimes 当前执行次数
* @return true 如果超过或者达到了上限
*/
protected boolean isLimitExceeded(int limit, int currentTimes) {
return currentTimes >= limit;
}
/**
* 超过次数上限,则不再输出,命令终止
*
* @param process the process to be aborted
* @param limit the limit to be printed
*/
protected void abortProcess(CommandProcess process, int limit) {
process.write("Command execution times exceed limit: " + limit
+ ", so command will exit. You can set it with -n option.\n");
process.end();
}
public boolean isVerbose() {
return verbose;
}
public void setVerbose(boolean verbose) {
this.verbose = verbose;
}
}
Markdown is supported
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment