remove unnecessary reflect in AdviceListenerAdapter

pull/1182/head
hengyunabc 5 years ago
parent ee0042cfc6
commit 6d186954c6

@ -0,0 +1,138 @@
package com.taobao.arthas.core.advisor;
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 Process process;
@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();
}
}

@ -4,43 +4,111 @@ import java.lang.reflect.Constructor;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import org.objectweb.asm.Type;
import com.taobao.arthas.core.util.StringUtils;
/**
* Arthas<br/>
* cinit/init/method
* Created by vlinux on 15/5/24.
*
* tt 使
*
* @author vlinux on 15/5/24
* @author hengyunabc 2020-05-20
*
*/
public class ArthasMethod {
private final Class<?> clazz;
private final String methodName;
private final String methodDesc;
private final int type;
private final Constructor<?> constructor;
private final Method method;
private Constructor<?> constructor;
private Method method;
/*
*
*/
private static final int TYPE_INIT = 1 << 1;
private void initMethod() {
if (constructor != null || method != null) {
return;
}
/*
*
*/
private static final int TYPE_METHOD = 1 << 2;
try {
ClassLoader loader = this.clazz.getClassLoader();
final org.objectweb.asm.Type asmType = org.objectweb.asm.Type.getMethodType(methodDesc);
// to arg types
final Class<?>[] argsClasses = new Class<?>[asmType.getArgumentTypes().length];
for (int index = 0; index < argsClasses.length; index++) {
// asm class descriptor to jvm class
final Class<?> argumentClass;
final Type argumentAsmType = asmType.getArgumentTypes()[index];
switch (argumentAsmType.getSort()) {
case Type.BOOLEAN: {
argumentClass = boolean.class;
break;
}
case Type.CHAR: {
argumentClass = char.class;
break;
}
case Type.BYTE: {
argumentClass = byte.class;
break;
}
case Type.SHORT: {
argumentClass = short.class;
break;
}
case Type.INT: {
argumentClass = int.class;
break;
}
case Type.FLOAT: {
argumentClass = float.class;
break;
}
case Type.LONG: {
argumentClass = long.class;
break;
}
case Type.DOUBLE: {
argumentClass = double.class;
break;
}
case Type.ARRAY: {
argumentClass = toClass(loader, argumentAsmType.getInternalName());
break;
}
case Type.VOID: {
argumentClass = void.class;
break;
}
case Type.OBJECT:
case Type.METHOD:
default: {
argumentClass = toClass(loader, argumentAsmType.getClassName());
break;
}
}
/**
*
*
* @return true/false
*/
public boolean isInit() {
return (TYPE_INIT & type) == TYPE_INIT;
argsClasses[index] = argumentClass;
}
/**
*
*
* @return true/false
*/
public boolean isMethod() {
return (TYPE_METHOD & type) == TYPE_METHOD;
if ("<init>".equals(this.methodName)) {
this.constructor = clazz.getDeclaredConstructor(argsClasses);
;
} else {
this.method = clazz.getDeclaredMethod(methodName, argsClasses);
}
} catch (Throwable e) {
throw new RuntimeException(e);
}
}
private Class<?> toClass(ClassLoader loader, String className) throws ClassNotFoundException {
return Class.forName(StringUtils.normalizeClassName(className), true, toClassLoader(loader));
}
private ClassLoader toClassLoader(ClassLoader loader) {
return null != loader ? loader : ArthasMethod.class.getClassLoader();
}
/**
@ -49,50 +117,53 @@ public class ArthasMethod {
* @return
*/
public String getName() {
return isInit()
? "<init>"
: method.getName();
return this.methodName;
}
@Override
public String toString() {
return isInit()
? constructor.toString()
: method.toString();
initMethod();
if (constructor != null) {
return constructor.toString();
} else if (method != null) {
return method.toString();
}
return "ERROR_METHOD";
}
public boolean isAccessible() {
return isInit()
? constructor.isAccessible()
: method.isAccessible();
initMethod();
if (this.method != null) {
return method.isAccessible();
} else if (this.constructor != null) {
return constructor.isAccessible();
}
return false;
}
public void setAccessible(boolean accessFlag) {
if (isInit()) {
initMethod();
if (constructor != null) {
constructor.setAccessible(accessFlag);
} else {
} else if (method != null) {
method.setAccessible(accessFlag);
}
}
public Object invoke(Object target, Object... args) throws IllegalAccessException, InvocationTargetException, InstantiationException {
return isInit()
? constructor.newInstance(args)
: method.invoke(target, args);
public Object invoke(Object target, Object... args)
throws IllegalAccessException, InvocationTargetException, InstantiationException {
initMethod();
if (method != null) {
return method.invoke(target, args);
} else if (this.constructor != null) {
return constructor.newInstance(args);
}
private ArthasMethod(int type, Constructor<?> constructor, Method method) {
this.type = type;
this.constructor = constructor;
this.method = method;
return null;
}
public static ArthasMethod newInit(Constructor<?> constructor) {
return new ArthasMethod(TYPE_INIT, constructor, null);
public ArthasMethod(Class<?> clazz, String methodName, String methodDesc) {
this.clazz = clazz;
this.methodName = methodName;
this.methodDesc = methodDesc;
}
public static ArthasMethod newMethod(Method method) {
return new ArthasMethod(TYPE_METHOD, null, method);
}
}

@ -1,241 +0,0 @@
package com.taobao.arthas.core.advisor;
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.ArthasCheckUtils;
import com.taobao.arthas.core.util.Constants;
import com.taobao.arthas.core.util.StringUtils;
import org.objectweb.asm.Type;
import java.lang.reflect.Constructor;
import java.lang.reflect.Method;
/**
* <br/>
* Class/MethodClassName/MethodName
*
*/
public abstract class ReflectAdviceListenerAdapter implements AdviceListener , ProcessAware{
private Process process;
@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;
}
private ClassLoader toClassLoader(ClassLoader loader) {
return null != loader
? loader
: AdviceListener.class.getClassLoader();
}
private Class<?> toClass(ClassLoader loader, String className) throws ClassNotFoundException {
return Class.forName(StringUtils.normalizeClassName(className), true, toClassLoader(loader));
}
private ArthasMethod toMethod(ClassLoader loader, Class<?> clazz, String methodName, String methodDesc)
throws ClassNotFoundException, NoSuchMethodException {
final org.objectweb.asm.Type asmType = org.objectweb.asm.Type.getMethodType(methodDesc);
// to arg types
final Class<?>[] argsClasses = new Class<?>[asmType.getArgumentTypes().length];
for (int index = 0; index < argsClasses.length; index++) {
// asm class descriptor to jvm class
final Class<?> argumentClass;
final Type argumentAsmType = asmType.getArgumentTypes()[index];
switch (argumentAsmType.getSort()) {
case Type.BOOLEAN: {
argumentClass = boolean.class;
break;
}
case Type.CHAR: {
argumentClass = char.class;
break;
}
case Type.BYTE: {
argumentClass = byte.class;
break;
}
case Type.SHORT: {
argumentClass = short.class;
break;
}
case Type.INT: {
argumentClass = int.class;
break;
}
case Type.FLOAT: {
argumentClass = float.class;
break;
}
case Type.LONG: {
argumentClass = long.class;
break;
}
case Type.DOUBLE: {
argumentClass = double.class;
break;
}
case Type.ARRAY: {
argumentClass = toClass(loader, argumentAsmType.getInternalName());
break;
}
case Type.VOID: {
argumentClass = void.class;
break;
}
case Type.OBJECT:
case Type.METHOD:
default: {
argumentClass = toClass(loader, argumentAsmType.getClassName());
break;
}
}
argsClasses[index] = argumentClass;
}
// to method or constructor
if (ArthasCheckUtils.isEquals(methodName, "<init>")) {
return ArthasMethod.newInit(toConstructor(clazz, argsClasses));
} else {
return ArthasMethod.newMethod(toMethod(clazz, methodName, argsClasses));
}
}
private Method toMethod(Class<?> clazz, String methodName, Class<?>[] argClasses) throws NoSuchMethodException {
return clazz.getDeclaredMethod(methodName, argClasses);
}
private Constructor<?> toConstructor(Class<?> clazz, Class<?>[] argClasses) throws NoSuchMethodException {
return clazz.getDeclaredConstructor(argClasses);
}
@Override
final public void before(
Class<?> clazz, String methodName, String methodDesc,
Object target, Object[] args) throws Throwable {
before(clazz.getClassLoader(), clazz, toMethod(clazz.getClassLoader(), 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, toMethod(clazz.getClassLoader(), 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, toMethod(clazz.getClassLoader(), 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();
}
}

@ -4,7 +4,7 @@ import com.alibaba.arthas.deps.org.slf4j.Logger;
import com.alibaba.arthas.deps.org.slf4j.LoggerFactory;
import com.taobao.arthas.core.advisor.Advice;
import com.taobao.arthas.core.advisor.ArthasMethod;
import com.taobao.arthas.core.advisor.ReflectAdviceListenerAdapter;
import com.taobao.arthas.core.advisor.AdviceListenerAdapter;
import com.taobao.arthas.core.shell.command.CommandProcess;
import com.taobao.arthas.core.util.LogUtil;
import com.taobao.arthas.core.util.ThreadLocalWatch;
@ -12,7 +12,7 @@ import com.taobao.arthas.core.util.ThreadLocalWatch;
/**
* @author ralf0131 2017-01-06 16:02.
*/
public class AbstractTraceAdviceListener extends ReflectAdviceListenerAdapter {
public class AbstractTraceAdviceListener extends AdviceListenerAdapter {
private static final Logger logger = LoggerFactory.getLogger(AbstractTraceAdviceListener.class);
protected final ThreadLocalWatch threadLocalWatch = new ThreadLocalWatch();
protected TraceCommand command;

@ -1,6 +1,6 @@
package com.taobao.arthas.core.command.monitor200;
import com.taobao.arthas.core.advisor.ReflectAdviceListenerAdapter;
import com.taobao.arthas.core.advisor.AdviceListenerAdapter;
import com.taobao.arthas.core.command.ScriptSupportCommand;
import com.taobao.arthas.core.shell.command.CommandProcess;
import com.taobao.arthas.core.advisor.Advice;
@ -11,7 +11,7 @@ import com.taobao.arthas.core.advisor.ArthasMethod;
* @author beiwei30 on 01/12/2016.
*/
@Deprecated
public class GroovyAdviceListener extends ReflectAdviceListenerAdapter {
public class GroovyAdviceListener extends AdviceListenerAdapter {
private ScriptSupportCommand.ScriptListener scriptListener;
private ScriptSupportCommand.Output output;

@ -1,6 +1,6 @@
package com.taobao.arthas.core.command.monitor200;
import com.taobao.arthas.core.advisor.ReflectAdviceListenerAdapter;
import com.taobao.arthas.core.advisor.AdviceListenerAdapter;
import com.taobao.arthas.core.shell.command.CommandProcess;
import com.taobao.arthas.core.advisor.ArthasMethod;
import com.taobao.arthas.core.util.ThreadLocalWatch;
@ -66,7 +66,7 @@ import static com.taobao.text.ui.Element.label;
*
* @author beiwei30 on 28/11/2016.
*/
class MonitorAdviceListener extends ReflectAdviceListenerAdapter {
class MonitorAdviceListener extends AdviceListenerAdapter {
// 输出定时任务
private Timer timer;
// 监控数据

@ -1,6 +1,6 @@
package com.taobao.arthas.core.command.monitor200;
import com.taobao.arthas.core.advisor.ReflectAdviceListenerAdapter;
import com.taobao.arthas.core.advisor.AdviceListenerAdapter;
import com.taobao.arthas.core.shell.command.CommandProcess;
import com.alibaba.arthas.deps.org.slf4j.Logger;
import com.alibaba.arthas.deps.org.slf4j.LoggerFactory;
@ -14,7 +14,7 @@ import com.taobao.arthas.core.util.ThreadUtil;
/**
* @author beiwei30 on 29/11/2016.
*/
public class StackAdviceListener extends ReflectAdviceListenerAdapter {
public class StackAdviceListener extends AdviceListenerAdapter {
private static final Logger logger = LoggerFactory.getLogger(StackAdviceListener.class);
private final ThreadLocal<String> stackThreadLocal = new ThreadLocal<String>();

@ -4,7 +4,7 @@ import com.alibaba.arthas.deps.org.slf4j.Logger;
import com.alibaba.arthas.deps.org.slf4j.LoggerFactory;
import com.taobao.arthas.core.advisor.Advice;
import com.taobao.arthas.core.advisor.ArthasMethod;
import com.taobao.arthas.core.advisor.ReflectAdviceListenerAdapter;
import com.taobao.arthas.core.advisor.AdviceListenerAdapter;
import com.taobao.arthas.core.shell.command.CommandProcess;
import com.taobao.arthas.core.util.DateUtils;
import com.taobao.arthas.core.util.LogUtil;
@ -15,7 +15,7 @@ import com.taobao.arthas.core.view.ObjectView;
/**
* @author beiwei30 on 29/11/2016.
*/
class WatchAdviceListener extends ReflectAdviceListenerAdapter {
class WatchAdviceListener extends AdviceListenerAdapter {
private static final Logger logger = LoggerFactory.getLogger(WatchAdviceListener.class);
private final ThreadLocalWatch threadLocalWatch = new ThreadLocalWatch();

Loading…
Cancel
Save