Arthas sm(查看已加载类的方法信息 )
@[toc]
# 二、命令列表
## 2.2 class/classloader相关命令
### 2.2.6 sm(查看已加载类的方法信息 )
> 提示:
>
> “Search-Method” 的简写,这个命令能搜索出所有已经加载了 Class 信息的方法信息。
>
> `sm` 命令只能看到由当前类所声明 (declaring) 的方法,父类则无法看到。
参数说明:
| 参数名称 | 参数说明 |
| --------------------- | ------------------------------------------ |
| *class-pattern* | 类名表达式匹配 |
| *method-pattern* | 方法名表达式匹配 |
| [d] | 展示每个方法的详细信息 |
| [E] | 开启正则表达式匹配,默认为通配符匹配 |
| `[c:]` | 指定 class 的 ClassLoader 的 hashcode |
| `[classLoaderClass:]` | 指定执行表达式的 ClassLoader 的 class name |
| `[n:]` | 具有详细信息的匹配类的最大数量(默认为 100 |
> 问题:这sm方法有啥用?我只能看出方法入参类型 返回类型等等,你又看不到具体的代码逻辑 感觉没用啊
答案:用途和好处
1. **了解方法签名**:`sm` 命令帮助你快速了解某个方法的签名信息。这包括方法的返回类型、参数类型以及访问修饰符(如 `public`, `private`, `static` 等)。这对于你在调试时确认方法调用的正确性非常重要。
2. **方法元数据**:通过 `sm -d` 命令,可以获取更详细的方法元数据,包括方法的声明类、修饰符、注解、异常等。这有助于了解方法的具体定义和它的上下文。
3. **分析方法的调用**:虽然 `sm` 命令不显示具体的代码逻辑,但了解方法的签名可以帮助你在其他调试任务中更好地理解方法的作用和调用。例如,在使用 `monitor` 或 `trace` 等命令时,你可以基于方法的签名来确认你正在监控或追踪正确的方法。
4. **验证方法的存在**:你可以使用 `sm` 命令验证一个类中是否存在某个方法,以及它的参数和返回类型是否符合你的预期。这在检查类的正确性或调试异常时非常有用。
5. **调试和分析**:在进行性能调优或分析时,了解方法的签名有助于你识别方法调用的瓶颈,或者确认方法是否按预期工作。
> 代码:
```
public class SMTaskCache
{
private static SMTaskCache instance = new SMTaskCache();
// 缓存
public static final Vector<SmconfigDmTaskMain> taskCache = new Vector<>();
// 读写锁
private final static ReadWriteLock lock = new ReentrantReadWriteLock();
public static SMTaskCache getInstance()
{
return instance;
}
private SMTaskCache()
{
}
/**
* 向缓存中添加对象
* @param info
*/
public static void add(SmconfigDmTaskMain info)
{
try
{
lock.writeLock().lock();
for (SmconfigDmTaskMain smconfigdmtaskmain : taskCache)
{
if (smconfigdmtaskmain.getSysTaskId().equals(info.getSysTaskId()))
{
taskCache.remove(smconfigdmtaskmain);
break;
}
}
taskCache.add(info);
}
finally
{
lock.writeLock().unlock();
}
}
/**
* 向缓存中添加对象
* @param infos
*/
@Autowired
public static void add(List<SmconfigDmTaskMain> infos)
{
try
{
lock.writeLock().lock();
for (SmconfigDmTaskMain info : infos)
{
add(info);
}
}
finally
{
lock.writeLock().unlock();
}
}
/**
* 从缓存中删除对象
* @param sysTaskId
*/
public static void remove(Long sysTaskId)
{
try
{
lock.writeLock().lock();
if (taskCache.size() > 0)
{
for (SmconfigDmTaskMain smconfigdmtaskmain : taskCache)
{
if (smconfigdmtaskmain.getSysTaskId().equals(sysTaskId))
{
taskCache.remove(smconfigdmtaskmain);
return;
}
}
}
}
finally
{
lock.writeLock().unlock();
}
}
/**
* 获取task状态
* @param smconfigdmtaskmain
* @return
*/
public static SmconfigDmTaskMain getTaskStatus(SmconfigDmTaskMain smconfigdmtaskmain)
{
try
{
lock.readLock().lock();
for (SmconfigDmTaskMain taski : taskCache)
{
if (taski.getSysTaskId().equals(smconfigdmtaskmain.getSysTaskId()))
{
smconfigdmtaskmain.setSysTaskState(taski.getSysTaskState());
smconfigdmtaskmain.setSysTaskNextTime(taski.getSysTaskNextTime());
smconfigdmtaskmain.setTaskSwitch(taski.getTaskSwitch());
}
}
return smconfigdmtaskmain;
}
finally
{
lock.readLock().unlock();
}
}
/**
* 获取task状态
* @param smconfigdmtaskmains
* @return
*/
public static List<SmconfigDmTaskMain> getTaskStatus(List<SmconfigDmTaskMain> smconfigdmtaskmains)
{
try
{
lock.readLock().lock();
for (SmconfigDmTaskMain smconfigdmtaskmain : smconfigdmtaskmains)
{
getTaskStatus(smconfigdmtaskmain);
}
return smconfigdmtaskmains;
}
finally
{
lock.readLock().unlock();
}
}
/**
* 初始化task状态
* @param sysTaskId
* @param nextTime
*/
public static void initTask(Long sysTaskId, Date nextTime, Integer taskSwitch)
{
try
{
lock.writeLock().lock();
Long curTime = System.currentTimeMillis();
for (SmconfigDmTaskMain smconfigdmtaskmain : taskCache)
{
if (smconfigdmtaskmain.getSysTaskId().equals(sysTaskId))
{//如果当前任务有结束时间,需要判断任务是否已经过期
if(smconfigdmtaskmain.getSysTaskEndTime() != null && smconfigdmtaskmain.getSysTaskEndTime().getTime() <= curTime){
smconfigdmtaskmain.setSysTaskState(SMTaskStatusEnum.PASTDUE.getCodeString());
smconfigdmtaskmain.setTaskSwitch(SMTaskSwitchEnum.INVALID.getCode());
}else if(SMTaskSwitchEnum.INVALID.getCode().equals(taskSwitch)){
smconfigdmtaskmain.setSysTaskState(SMTaskStatusEnum.PAUSE.getCodeString());
smconfigdmtaskmain.setTaskSwitch(SMTaskSwitchEnum.INVALID.getCode());
}else{
smconfigdmtaskmain.setSysTaskState(SMTaskStatusEnum.READY.getCodeString());
smconfigdmtaskmain.setTaskSwitch(SMTaskSwitchEnum.ACTIVE.getCode());
}
smconfigdmtaskmain.setSysTaskNextTime(nextTime);
}
}
}
finally
{
lock.writeLock().unlock();
}
}
/**
* 更新task状态为暂停
* @param sysTaskId
*/
public static void pasueTask(Long sysTaskId)
{
try
{
lock.writeLock().lock();
Long curTime = System.currentTimeMillis();
for (SmconfigDmTaskMain smconfigdmtaskmain : taskCache)
{
if (smconfigdmtaskmain.getSysTaskId().equals(sysTaskId))
{//如果当前任务有结束时间,需要判断任务是否已经过期
if(smconfigdmtaskmain.getSysTaskEndTime() != null && smconfigdmtaskmain.getSysTaskEndTime().getTime() <= curTime){
smconfigdmtaskmain.setSysTaskState(SMTaskStatusEnum.PASTDUE.getCodeString());
smconfigdmtaskmain.setTaskSwitch(SMTaskSwitchEnum.INVALID.getCode());
}else {
smconfigdmtaskmain.setSysTaskState(SMTaskStatusEnum.PAUSE.getCodeString());
smconfigdmtaskmain.setTaskSwitch(SMTaskSwitchEnum.INVALID.getCode());
}
}
}
}
finally
{
lock.writeLock().unlock();
}
}
/**
* 开始任务
* @param sysTaskId
* @param nextTime
*/
public static void executeTask(Long sysTaskId, Date nextTime)
{
try
{
lock.writeLock().lock();
Long curTime = System.currentTimeMillis();
for (SmconfigDmTaskMain smconfigdmtaskmain : taskCache)
{
if (smconfigdmtaskmain.getSysTaskId().equals(sysTaskId))
{
//如果当前任务有结束时间,需要判断任务是否已经过期
if(smconfigdmtaskmain.getSysTaskEndTime() != null && smconfigdmtaskmain.getSysTaskEndTime().getTime() <= curTime){
smconfigdmtaskmain.setSysTaskState(SMTaskStatusEnum.PASTDUE.getCodeString());
smconfigdmtaskmain.setTaskSwitch(SMTaskSwitchEnum.INVALID.getCode());
}else{
smconfigdmtaskmain.setSysTaskState(SMTaskStatusEnum.EXECUTING.getCodeString());
smconfigdmtaskmain.setTaskSwitch(SMTaskSwitchEnum.ACTIVE.getCode());
}
smconfigdmtaskmain.setSysTaskNextTime(nextTime);
}
}
}
finally
{
lock.writeLock().unlock();
}
}
/**
* 结束任务
* @param sysTaskId 任务ID
* @param externalCallFlag 【true:为外部接口curl命令调用;false:系统任务内部调用】
*/
public static void executeTaskEnd(Long sysTaskId, boolean externalCallFlag)
{
//如果externalCallFlag为true,则不修改系统任务的状态,直接跳过
if (externalCallFlag) {
return;
}
try
{
lock.writeLock().lock();
Long curTime = System.currentTimeMillis();
for (SmconfigDmTaskMain smconfigdmtaskmain : taskCache)
{
if (smconfigdmtaskmain.getSysTaskId().equals(sysTaskId))
{
//如果当前任务有结束时间,需要判断任务是否已经过期
if(smconfigdmtaskmain.getSysTaskEndTime() != null && smconfigdmtaskmain.getSysTaskEndTime().getTime() <= curTime){
smconfigdmtaskmain.setSysTaskState(SMTaskStatusEnum.PASTDUE.getCodeString());
smconfigdmtaskmain.setTaskSwitch(SMTaskSwitchEnum.INVALID.getCode());
}else{
smconfigdmtaskmain.setTaskSwitch(SMTaskSwitchEnum.ACTIVE.getCode());
smconfigdmtaskmain.setSysTaskState(SMTaskStatusEnum.READY.getCodeString());
}
}
}
}
finally
{
lock.writeLock().unlock();
}
}
}
```
#### 举例1:显示类加载的方法
> `基础语法`:
>
> sm 全路径类名
```
[arthas@18139]$ sm com.hero.lte.ems.sysmanager.cache.SMTaskCache
com.hero.lte.ems.sysmanager.cache.SMTaskCache <init>()V
com.hero.lte.ems.sysmanager.cache.SMTaskCache executeTask(Ljava/lang/Long;Ljava/util/Date;)V
com.hero.lte.ems.sysmanager.cache.SMTaskCache getTaskStatus(Lcom/hero/lte/ems/sysmanager/model/SmconfigDmTaskMain;)Lcom/hero/lte/ems/sysmanager/model/SmconfigDmTaskMain;
com.hero.lte.ems.sysmanager.cache.SMTaskCache getTaskStatus(Ljava/util/List;)Ljava/util/List;
com.hero.lte.ems.sysmanager.cache.SMTaskCache initTask(Ljava/lang/Long;Ljava/util/Date;Ljava/lang/Integer;)V
com.hero.lte.ems.sysmanager.cache.SMTaskCache pasueTask(Ljava/lang/Long;)V
com.hero.lte.ems.sysmanager.cache.SMTaskCache executeTaskEnd(Ljava/lang/Long;Z)V
com.hero.lte.ems.sysmanager.cache.SMTaskCache add(Lcom/hero/lte/ems/sysmanager/model/SmconfigDmTaskMain;)V
com.hero.lte.ems.sysmanager.cache.SMTaskCache add(Ljava/util/List;)V
com.hero.lte.ems.sysmanager.cache.SMTaskCache remove(Ljava/lang/Long;)V
com.hero.lte.ems.sysmanager.cache.SMTaskCache getInstance()Lcom/hero/lte/ems/sysmanager/cache/SMTaskCache;
Affect(row-cnt:11) cost in 18 ms.
[arthas@18139]$
```
#### 举例2:显示类加载的executeTask方法详细信息
> `基础语法`:
>
> sm -d 全路径类名 方法名
```
[arthas@18139]$ sm -d com.hero.lte.ems.sysmanager.cache.SMTaskCache executeTask
declaring-class com.hero.lte.ems.sysmanager.cache.SMTaskCache
method-name executeTask
modifier public,static
annotation
parameters java.lang.Long
java.util.Date
return void
exceptions
classLoaderHash 18b4aac2
Affect(row-cnt:1) cost in 15 ms.
[arthas@18139]$
```
# 本人其他相关文章链接
1.[Arthas 全攻略:让调试变得简单](https://blog.csdn.net/a924382407/article/details/142364049)
2.[Arthas dashboard(当前系统的实时数据面板)](https://blog.csdn.net/a924382407/article/details/142364494)
3.[Arthas thread(查看当前JVM的线程堆栈信息)](https://blog.csdn.net/a924382407/article/details/142364804)
4.[Arthas jvm(查看当前JVM的信息)](https://blog.csdn.net/a924382407/article/details/142375718)
5.[Arthas sysprop(查看和修改JVM的系统属性)](https://blog.csdn.net/a924382407/article/details/142375804)
6.[Arthas sysenv(查看JVM的环境变量)](https://blog.csdn.net/a924382407/article/details/142412678)
7.[Arthas vmoption(查看和修改 JVM里诊断相关的option)](https://blog.csdn.net/a924382407/article/details/142413168)
8.[Arthas getstatic(查看类的静态属性 )](https://blog.csdn.net/a924382407/article/details/142439923)
9.[Arthas heapdump(dump java heap, 类似 jmap 命令的 heap dump 功能)](https://blog.csdn.net/a924382407/article/details/142439965)
10.[Arthas logger(查看 logger 信息,更新 logger level)](https://blog.csdn.net/a924382407/article/details/142449630)
11.[Arthas mbean(查看 Mbean 的信息)](https://blog.csdn.net/a924382407/article/details/142449757)
12.[Arthas memory(查看 JVM 内存信息)](https://blog.csdn.net/a924382407/article/details/142584365)
13.[Arthas ognl(执行ognl表达式)](https://blog.csdn.net/a924382407/article/details/142478538)
14.[Arthas perfcounter(查看当前 JVM 的 Perf Counter 信息)](https://blog.csdn.net/a924382407/article/details/142478615)
15.[Arthas vmtool(从 jvm 里查询对象,执行 forceGc)](https://blog.csdn.net/a924382407/article/details/142560369)
16.[Arthas jad(字节码文件反编译成源代码 )](https://blog.csdn.net/a924382407/article/details/142561044)
17.[Arthas mc(Memory Compiler/内存编译器 )](https://blog.csdn.net/a924382407/article/details/142584154)
18.[Arthas redefine(加载外部的.class文件,redefine到JVM里 )](https://blog.csdn.net/a924382407/article/details/142584223)
19.[Arthas classloader (查看 classloader 的继承树,urls,类加载信息)](https://blog.csdn.net/a924382407/article/details/142611407)
20.[Arthas sc(查看JVM已加载的类信息 )](https://blog.csdn.net/a924382407/article/details/142611489)
21.[Arthas sm(查看已加载类的方法信息 )](https://blog.csdn.net/a924382407/article/details/142627032)
22.[Arthas monitor(方法执行监控)](https://blog.csdn.net/a924382407/article/details/142627079)
23.[Arthas stack (输出当前方法被调用的调用路径)](https://blog.csdn.net/a924382407/article/details/142632032)
24.[Arthas trace (方法内部调用路径,并输出方法路径上的每个节点上耗时)](https://blog.csdn.net/a924382407/article/details/142632064)
25.[Arthas tt(方法执行数据的时空隧道,记录下指定方法每次调用的入参和返回信息,并能对这些不同的时间下调用进行观测)](https://blog.csdn.net/a924382407/article/details/142632103)
26.[Arthas watch (方法执行数据观测)](https://blog.csdn.net/a924382407/article/details/142632132)
27.[Arthas profiler(使用async-profiler对应用采样,生成火焰图)](https://blog.csdn.net/a924382407/article/details/142632165)
- 点赞
- 收藏
- 关注作者
评论(0)