Add --classLoaderClass for sc/sm (#1433)

This commit is contained in:
Hollow Man
2020-08-18 14:00:52 +08:00
committed by GitHub
parent 1bfda2b827
commit ea262bd52b
10 changed files with 120 additions and 1 deletions
@@ -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();