mirror of
https://github.com/alibaba/arthas.git
synced 2024-04-21 10:21:39 +00:00
Add --classLoaderClass for sc/sm (#1433)
This commit is contained in:
@@ -3,6 +3,7 @@ package com.taobao.arthas.core.command.klass100;
|
||||
|
||||
import java.lang.instrument.Instrumentation;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.Comparator;
|
||||
import java.util.List;
|
||||
@@ -11,11 +12,13 @@ import com.taobao.arthas.core.command.Constants;
|
||||
import com.taobao.arthas.core.command.model.ClassDetailVO;
|
||||
import com.taobao.arthas.core.command.model.SearchClassModel;
|
||||
import com.taobao.arthas.core.command.model.RowAffectModel;
|
||||
import com.taobao.arthas.core.command.model.ClassLoaderVO;
|
||||
import com.taobao.arthas.core.shell.cli.Completion;
|
||||
import com.taobao.arthas.core.shell.cli.CompletionUtils;
|
||||
import com.taobao.arthas.core.shell.command.AnnotatedCommand;
|
||||
import com.taobao.arthas.core.shell.command.CommandProcess;
|
||||
import com.taobao.arthas.core.util.ClassUtils;
|
||||
import com.taobao.arthas.core.util.ClassLoaderUtils;
|
||||
import com.taobao.arthas.core.util.ResultUtils;
|
||||
import com.taobao.arthas.core.util.SearchUtils;
|
||||
import com.taobao.arthas.core.util.StringUtils;
|
||||
@@ -46,6 +49,7 @@ public class SearchClassCommand extends AnnotatedCommand {
|
||||
private boolean isField = false;
|
||||
private boolean isRegEx = false;
|
||||
private String hashCode = null;
|
||||
private String classLoaderClass;
|
||||
private Integer expand;
|
||||
private int numberOfLimit = 100;
|
||||
|
||||
@@ -85,6 +89,12 @@ public class SearchClassCommand extends AnnotatedCommand {
|
||||
this.hashCode = hashCode;
|
||||
}
|
||||
|
||||
@Option(longName = "classLoaderClass")
|
||||
@Description("The class name of the special class's classLoader.")
|
||||
public void setClassLoaderClass(String classLoaderClass) {
|
||||
this.classLoaderClass = classLoaderClass;
|
||||
}
|
||||
|
||||
@Option(shortName = "n", longName = "limits")
|
||||
@Description("Maximum number of matching classes with details (100 by default)")
|
||||
public void setNumberOfLimit(int numberOfLimit) {
|
||||
@@ -96,6 +106,25 @@ public class SearchClassCommand extends AnnotatedCommand {
|
||||
// TODO: null check
|
||||
RowAffect affect = new RowAffect();
|
||||
Instrumentation inst = process.session().getInstrumentation();
|
||||
|
||||
if (hashCode == null && classLoaderClass != null) {
|
||||
List<ClassLoader> matchedClassLoaders = ClassLoaderUtils.getClassLoaderByClassName(inst, classLoaderClass);
|
||||
if (matchedClassLoaders.size() == 1) {
|
||||
hashCode = Integer.toHexString(matchedClassLoaders.get(0).hashCode());
|
||||
} else if (matchedClassLoaders.size() > 1) {
|
||||
Collection<ClassLoaderVO> classLoaderVOList = ClassUtils.createClassLoaderVOList(matchedClassLoaders);
|
||||
SearchClassModel searchclassModel = new SearchClassModel()
|
||||
.setClassLoaderClass(classLoaderClass)
|
||||
.setMatchedClassLoaders(classLoaderVOList);
|
||||
process.appendResult(searchclassModel);
|
||||
process.end(-1, "Found more than one classloader by class name, please specify classloader with '-c <classloader hash>'");
|
||||
return;
|
||||
} else {
|
||||
process.end(-1, "Can not find classloader by class name: " + classLoaderClass + ".");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
List<Class<?>> matchedClasses = new ArrayList<Class<?>>(SearchUtils.searchClass(inst, classPattern, isRegEx, hashCode));
|
||||
Collections.sort(matchedClasses, new Comparator<Class<?>>() {
|
||||
@Override
|
||||
|
||||
@@ -5,6 +5,8 @@ import java.lang.instrument.Instrumentation;
|
||||
import java.lang.reflect.Constructor;
|
||||
import java.lang.reflect.Method;
|
||||
import java.util.Set;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
import com.alibaba.arthas.deps.org.slf4j.Logger;
|
||||
import com.alibaba.arthas.deps.org.slf4j.LoggerFactory;
|
||||
@@ -12,11 +14,13 @@ import com.taobao.arthas.core.command.Constants;
|
||||
import com.taobao.arthas.core.command.model.SearchMethodModel;
|
||||
import com.taobao.arthas.core.command.model.MethodVO;
|
||||
import com.taobao.arthas.core.command.model.RowAffectModel;
|
||||
import com.taobao.arthas.core.command.model.ClassLoaderVO;
|
||||
import com.taobao.arthas.core.shell.cli.Completion;
|
||||
import com.taobao.arthas.core.shell.cli.CompletionUtils;
|
||||
import com.taobao.arthas.core.shell.command.AnnotatedCommand;
|
||||
import com.taobao.arthas.core.shell.command.CommandProcess;
|
||||
import com.taobao.arthas.core.util.ClassUtils;
|
||||
import com.taobao.arthas.core.util.ClassLoaderUtils;
|
||||
import com.taobao.arthas.core.util.SearchUtils;
|
||||
import com.taobao.arthas.core.util.StringUtils;
|
||||
import com.taobao.arthas.core.util.affect.RowAffect;
|
||||
@@ -50,6 +54,7 @@ public class SearchMethodCommand extends AnnotatedCommand {
|
||||
private String classPattern;
|
||||
private String methodPattern;
|
||||
private String hashCode = null;
|
||||
private String classLoaderClass;
|
||||
private boolean isDetail = false;
|
||||
private boolean isRegEx = false;
|
||||
private int numberOfLimit = 100;
|
||||
@@ -84,6 +89,12 @@ public class SearchMethodCommand extends AnnotatedCommand {
|
||||
this.hashCode = hashCode;
|
||||
}
|
||||
|
||||
@Option(longName = "classLoaderClass")
|
||||
@Description("The class name of the special class's classLoader.")
|
||||
public void setClassLoaderClass(String classLoaderClass) {
|
||||
this.classLoaderClass = classLoaderClass;
|
||||
}
|
||||
|
||||
@Option(shortName = "n", longName = "limits")
|
||||
@Description("Maximum number of matching classes (100 by default)")
|
||||
public void setNumberOfLimit(int numberOfLimit) {
|
||||
@@ -96,6 +107,25 @@ public class SearchMethodCommand extends AnnotatedCommand {
|
||||
|
||||
Instrumentation inst = process.session().getInstrumentation();
|
||||
Matcher<String> methodNameMatcher = methodNameMatcher();
|
||||
|
||||
if (hashCode == null && classLoaderClass != null) {
|
||||
List<ClassLoader> matchedClassLoaders = ClassLoaderUtils.getClassLoaderByClassName(inst, classLoaderClass);
|
||||
if (matchedClassLoaders.size() == 1) {
|
||||
hashCode = Integer.toHexString(matchedClassLoaders.get(0).hashCode());
|
||||
} else if (matchedClassLoaders.size() > 1) {
|
||||
Collection<ClassLoaderVO> classLoaderVOList = ClassUtils.createClassLoaderVOList(matchedClassLoaders);
|
||||
SearchMethodModel searchmethodModel = new SearchMethodModel()
|
||||
.setClassLoaderClass(classLoaderClass)
|
||||
.setMatchedClassLoaders(classLoaderVOList);
|
||||
process.appendResult(searchmethodModel);
|
||||
process.end(-1, "Found more than one classloader by class name, please specify classloader with '-c <classloader hash>'");
|
||||
return;
|
||||
} else {
|
||||
process.end(-1, "Can not find classloader by class name: " + classLoaderClass + ".");
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
Set<Class<?>> matchedClasses = SearchUtils.searchClass(inst, classPattern, isRegEx, hashCode);
|
||||
|
||||
if (numberOfLimit > 0 && matchedClasses.size() > numberOfLimit) {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
package com.taobao.arthas.core.command.model;
|
||||
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
@@ -15,6 +15,9 @@ public class SearchClassModel extends ResultModel {
|
||||
private List<String> classNames;
|
||||
private int segment;
|
||||
|
||||
private Collection<ClassLoaderVO> matchedClassLoaders;
|
||||
private String classLoaderClass;
|
||||
|
||||
public SearchClassModel() {
|
||||
}
|
||||
|
||||
@@ -70,4 +73,22 @@ public class SearchClassModel extends ResultModel {
|
||||
public Integer getExpand() {
|
||||
return expand;
|
||||
}
|
||||
|
||||
public String getClassLoaderClass() {
|
||||
return classLoaderClass;
|
||||
}
|
||||
|
||||
public SearchClassModel setClassLoaderClass(String classLoaderClass) {
|
||||
this.classLoaderClass = classLoaderClass;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Collection<ClassLoaderVO> getMatchedClassLoaders() {
|
||||
return matchedClassLoaders;
|
||||
}
|
||||
|
||||
public SearchClassModel setMatchedClassLoaders(Collection<ClassLoaderVO> matchedClassLoaders) {
|
||||
this.matchedClassLoaders = matchedClassLoaders;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package com.taobao.arthas.core.command.model;
|
||||
|
||||
import java.util.Collection;
|
||||
|
||||
/**
|
||||
* Model of SearchMethodCommand
|
||||
@@ -9,6 +10,9 @@ public class SearchMethodModel extends ResultModel {
|
||||
private MethodVO methodInfo;
|
||||
private boolean detail;
|
||||
|
||||
private Collection<ClassLoaderVO> matchedClassLoaders;
|
||||
private String classLoaderClass;
|
||||
|
||||
public SearchMethodModel() {
|
||||
}
|
||||
|
||||
@@ -33,6 +37,24 @@ public class SearchMethodModel extends ResultModel {
|
||||
this.detail = detail;
|
||||
}
|
||||
|
||||
public String getClassLoaderClass() {
|
||||
return classLoaderClass;
|
||||
}
|
||||
|
||||
public SearchMethodModel setClassLoaderClass(String classLoaderClass) {
|
||||
this.classLoaderClass = classLoaderClass;
|
||||
return this;
|
||||
}
|
||||
|
||||
public Collection<ClassLoaderVO> getMatchedClassLoaders() {
|
||||
return matchedClassLoaders;
|
||||
}
|
||||
|
||||
public SearchMethodModel setMatchedClassLoaders(Collection<ClassLoaderVO> matchedClassLoaders) {
|
||||
this.matchedClassLoaders = matchedClassLoaders;
|
||||
return this;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getType() {
|
||||
return "sm";
|
||||
|
||||
@@ -11,6 +11,12 @@ import com.taobao.text.util.RenderUtil;
|
||||
public class SearchClassView extends ResultView<SearchClassModel> {
|
||||
@Override
|
||||
public void draw(CommandProcess process, SearchClassModel result) {
|
||||
if (result.getMatchedClassLoaders() != null) {
|
||||
process.write("Matched classloaders: \n");
|
||||
ClassLoaderView.drawClassLoaders(process, result.getMatchedClassLoaders(), false);
|
||||
process.write("\n");
|
||||
return;
|
||||
}
|
||||
|
||||
if (result.isDetailed()) {
|
||||
process.write(RenderUtil.render(ClassUtils.renderClassInfo(result.getClassInfo(),
|
||||
|
||||
@@ -14,6 +14,13 @@ import com.taobao.text.util.RenderUtil;
|
||||
public class SearchMethodView extends ResultView<SearchMethodModel> {
|
||||
@Override
|
||||
public void draw(CommandProcess process, SearchMethodModel result) {
|
||||
if (result.getMatchedClassLoaders() != null) {
|
||||
process.write("Matched classloaders: \n");
|
||||
ClassLoaderView.drawClassLoaders(process, result.getMatchedClassLoaders(), false);
|
||||
process.write("\n");
|
||||
return;
|
||||
}
|
||||
|
||||
boolean detail = result.isDetail();
|
||||
MethodVO methodInfo = result.getMethodInfo();
|
||||
|
||||
|
||||
@@ -18,6 +18,7 @@ sc
|
||||
|`[f]`|print the fields info of the current class, MUST be used with `-d` together|
|
||||
|`[x:]`|specify the depth of recursive traverse the static fields, the default value is '0' - equivalent to use `toString` to output|
|
||||
|`[c:]`|The hash code of the special class's classLoader|
|
||||
|`[classLoaderClass:]`| The class name of the ClassLoader that executes the expression. |
|
||||
|`[n:]`|Maximum number of matching classes with details (100 by default)|
|
||||
|
||||
> *class-patten* supports full qualified class name, e.g. com.taobao.test.AAA and com/taobao/test/AAA. It also supports the format of 'com/taobao/test/AAA', so that it is convenient to directly copy class name from the exception stack trace without replacing '/' to '.'. <br/><br/>
|
||||
|
||||
@@ -17,6 +17,7 @@ sm
|
||||
|`[d]`|print the details of the method|
|
||||
|`[E]`|turn on regex matching while the default mode is wildcard matching|
|
||||
|`[c:]`|The hash code of the special class's classLoader|
|
||||
|`[classLoaderClass:]`| The class name of the ClassLoader that executes the expression. |
|
||||
|`[n:]`|Maximum number of matching classes with details (100 by default)|
|
||||
|
||||
### Usage
|
||||
|
||||
@@ -21,6 +21,7 @@ sc
|
||||
|[f]|输出当前类的成员变量信息(需要配合参数-d一起使用)|
|
||||
|[x:]|指定输出静态变量时属性的遍历深度,默认为 0,即直接使用 `toString` 输出|
|
||||
|`[c:]`|指定class的 ClassLoader 的 hashcode|
|
||||
|`[classLoaderClass:]`|指定执行表达式的 ClassLoader 的 class name|
|
||||
|`[n:]`|具有详细信息的匹配类的最大数量(默认为100)|
|
||||
|
||||
> class-pattern支持全限定名,如com.taobao.test.AAA,也支持com/taobao/test/AAA这样的格式,这样,我们从异常堆栈里面把类名拷贝过来的时候,不需要在手动把`/`替换为`.`啦。
|
||||
|
||||
@@ -18,6 +18,7 @@ sm
|
||||
|[d]|展示每个方法的详细信息|
|
||||
|[E]|开启正则表达式匹配,默认为通配符匹配|
|
||||
|`[c:]`|指定class的 ClassLoader 的 hashcode|
|
||||
|`[classLoaderClass:]`|指定执行表达式的 ClassLoader 的 class name|
|
||||
|`[n:]`|具有详细信息的匹配类的最大数量(默认为100)|
|
||||
|
||||
### 使用参考
|
||||
|
||||
Reference in New Issue
Block a user