标签:mis 线程id @Value manager map sso interrupt group net
有时候在生产或者测试环境有些方法执行比较耗时,一种简单粗暴的方法是在可能的地点打日志进行监视,另一种就是借助于插件进行检测。最近也是有机会了解并实际运用了arthas这个插件,还是挺方便的。而且也可以用于查看JVM信息、线程信息以及系统属性等信息。
arthas: https://arthas.aliyun.com/zh-cn/
下载:
curl -O https://arthas.aliyun.com/arthas-boot.jar
package arthas; public class ArthasTest { public static void main(String[] args) { System.out.println(Thread.currentThread().getName()); String test = System.getProperty("test"); while (true) { String test2 = System.getProperty("test"); if (test2 != null && !test2.equals(test)) { System.out.println(test2); test = test2; } } } }
启动该主类
C:\Users\qlq\Desktop\plaintools>java -jar arthas-boot.jar [INFO] arthas-boot version: 3.4.5 [INFO] Found existing java process, please choose one and input the serial number of the process, eg : 1. Then hit ENTER. * [1]: 20384 org.jetbrains.idea.maven.server.RemoteMavenServer36 [2]: 1556 [3]: 28868 arthas.ArthasTest [4]: 16780 org.jetbrains.jps.cmdline.Launcher [5]: 7676 org.jetbrains.jps.cmdline.Launcher 3 [INFO] local lastest version: 3.4.5, remote lastest version: 3.4.6, try to download from remote. [INFO] Start download arthas from remote server: https://arthas.aliyun.com/download/3.4.6?mirror=aliyun [INFO] File size: 11.99 MB, downloaded size: 813.01 KB, downloading ... [INFO] File size: 11.99 MB, downloaded size: 1.58 MB, downloading ... [INFO] File size: 11.99 MB, downloaded size: 2.36 MB, downloading ... [INFO] File size: 11.99 MB, downloaded size: 3.14 MB, downloading ... [INFO] File size: 11.99 MB, downloaded size: 3.93 MB, downloading ... [INFO] File size: 11.99 MB, downloaded size: 4.71 MB, downloading ... [INFO] File size: 11.99 MB, downloaded size: 5.49 MB, downloading ... [INFO] File size: 11.99 MB, downloaded size: 6.28 MB, downloading ... [INFO] File size: 11.99 MB, downloaded size: 7.06 MB, downloading ... [INFO] File size: 11.99 MB, downloaded size: 7.33 MB, downloading ... [INFO] File size: 11.99 MB, downloaded size: 8.81 MB, downloading ... [INFO] File size: 11.99 MB, downloaded size: 9.59 MB, downloading ... [INFO] File size: 11.99 MB, downloaded size: 10.37 MB, downloading ... [INFO] File size: 11.99 MB, downloaded size: 11.56 MB, downloading ... [INFO] Download arthas success. [INFO] arthas home: C:\Users\jxrt\.arthas\lib\3.4.6\arthas [INFO] Try to attach process 28868 [INFO] Found java home from System Env JAVA_HOME: E:\java\JAVA8 [INFO] Attach process 28868 success. [INFO] arthas-client connect 127.0.0.1 3658 ,---. ,------. ,--------.,--. ,--. ,---. ,---. / O \ | .--. ‘‘--. .--‘| ‘--‘ | / O \ ‘ .-‘ | .-. || ‘--‘.‘ | | | .--. || .-. |`. `-. | | | || |\ \ | | | | | || | | |.-‘ | `--‘ `--‘`--‘ ‘--‘ `--‘ `--‘ `--‘`--‘ `--‘`-----‘ wiki https://arthas.aliyun.com/doc tutorials https://arthas.aliyun.com/doc/arthas-tutorials.html version 3.4.6 pid 28868 time 2021-01-12 20:54:40 [arthas@28868]$
arthas 会自动检测进程ID,需要自己选择一个PID然后进入,上面我输入3
1.dashboard 当前系统的实时数据面板:包括线程、JVM、操作系统属性等
[arthas@28868]$ dashboard ID NAME GROUP PRIORITY STATE %CPU DELTA_TIME TIME INTERRUPTED DAEMON 1 main main 5 RUNNABLE 0.0 0.000 6:9.250 false false -1 C1 CompilerThread3 - -1 - 0.0 0.000 0:0.546 false true -1 C2 CompilerThread2 - -1 - 0.0 0.000 0:0.296 false true -1 C2 CompilerThread0 - -1 - 0.0 0.000 0:0.281 false true -1 C2 CompilerThread1 - -1 - 0.0 0.000 0:0.203 false true 25 arthas-NettyHttpTelnetBootstrap-3-2 system 5 RUNNABLE 0.0 0.000 0:0.078 false true 5 Attach Listener system 5 RUNNABLE 0.0 0.000 0:0.046 false true -1 VM Thread - -1 - 0.0 0.000 0:0.031 false true 2 Reference Handler system 10 WAITING 0.0 0.000 0:0.015 false true 3 Finalizer system 8 WAITING 0.0 0.000 0:0.015 false true 18 arthas-NettyHttpTelnetBootstrap-3-1 system 5 RUNNABLE 0.0 0.000 0:0.015 false true 26 arthas-command-execute system 5 TIMED_WAITING 0.0 0.000 0:0.015 false true 4 Signal Dispatcher system 9 RUNNABLE 0.0 0.000 0:0.000 false true 15 arthas-timer system 5 WAITING 0.0 0.000 0:0.000 false true 19 arthas-NettyWebsocketTtyBootstrap-4-1 system 5 RUNNABLE 0.0 0.000 0:0.000 false true 20 arthas-NettyWebsocketTtyBootstrap-4-2 system 5 RUNNABLE 0.0 0.000 0:0.000 false true 21 arthas-shell-server system 5 TIMED_WAITING 0.0 0.000 0:0.000 false true 22 arthas-session-manager system 5 TIMED_WAITING 0.0 0.000 0:0.000 false true 23 arthas-UserStat system 5 WAITING 0.0 0.000 0:0.000 false true 27 Timer-for-arthas-dashboard-2d53a13f-e23f-4 system 5 RUNNABLE 0.0 0.000 0:0.000 false true -1 GC task thread#7 (ParallelGC) - -1 - 0.0 0.000 0:0.000 false true -1 GC task thread#6 (ParallelGC) - -1 - 0.0 0.000 0:0.000 false true -1 VM Periodic Task Thread - -1 - 0.0 0.000 0:0.000 false true -1 GC task thread#0 (ParallelGC) - -1 - 0.0 0.000 0:0.000 false true -1 Service Thread - -1 - 0.0 0.000 0:0.000 false true -1 GC task thread#1 (ParallelGC) - -1 - 0.0 0.000 0:0.000 false true -1 GC task thread#2 (ParallelGC) - -1 - 0.0 0.000 0:0.000 false true Memory used total max usage GC heap 58M 241M 3582M 1.64% gc.ps_scavenge.count 1 ps_eden_space 50M 63M 1322M 3.80% gc.ps_scavenge.time(ms) 7 ps_survivor_space 8M 10M 10M 79.64% gc.ps_marksweep.count 0 ps_old_gen 88K 172032K 2751488K 0.00% gc.ps_marksweep.time(ms) 0 nonheap 27M 28M -1 96.88% code_cache 5M 5M 240M 2.21% metaspace 19M 20M -1 96.71% compressed_class_space 2M 2M 1024M 0.23% direct 0K 0K - 105.88% mapped 0K 0K - 0.00% Runtime os.name Windows 10 os.version 10.0 java.version 1.8.0_171 java.home E:\java\JAVA8_171\jre systemload.average -1.00 processors 8 timestamp/uptime Tue Jan 12 20:56:26 CST 2021/370s
2.thread 查看线程信息
[arthas@28868]$ thread Threads Total: 29, NEW: 0, RUNNABLE: 8, BLOCKED: 0, WAITING: 4, TIMED_WAITING: 2, TERMINATED: 0, Internal threads: 15 ID NAME GROUP PRIORITY STATE %CPU DELTA_TIME TIME INTERRUPTED DAEMON 1 main main 5 RUNNABLE 101.42 0.203 8:3.609 false false 2 Reference Handler system 10 WAITING 0.0 0.000 0:0.015 false true 3 Finalizer system 8 WAITING 0.0 0.000 0:0.015 false true 4 Signal Dispatcher system 9 RUNNABLE 0.0 0.000 0:0.000 false true 5 Attach Listener system 5 RUNNABLE 0.0 0.000 0:0.046 false true 15 arthas-timer system 5 WAITING 0.0 0.000 0:0.000 false true 18 arthas-NettyHttpTelnetBootstrap-3-1 system 5 RUNNABLE 0.0 0.000 0:0.015 false true 19 arthas-NettyWebsocketTtyBootstrap-4-1 system 5 RUNNABLE 0.0 0.000 0:0.000 false true 20 arthas-NettyWebsocketTtyBootstrap-4-2 system 5 RUNNABLE 0.0 0.000 0:0.000 false true 21 arthas-shell-server system 5 TIMED_WAITING 0.0 0.000 0:0.000 false true 22 arthas-session-manager system 5 TIMED_WAITING 0.0 0.000 0:0.000 false true 23 arthas-UserStat system 5 WAITING 0.0 0.000 0:0.000 false true 25 arthas-NettyHttpTelnetBootstrap-3-2 system 5 RUNNABLE 0.0 0.000 0:0.125 false true 26 arthas-command-execute system 5 RUNNABLE 0.0 0.000 0:0.015 false true -1 C2 CompilerThread2 - -1 - 0.0 0.000 0:0.328 false true -1 GC task thread#7 (ParallelGC) - -1 - 0.0 0.000 0:0.000 false true -1 GC task thread#6 (ParallelGC) - -1 - 0.0 0.000 0:0.000 false true -1 VM Periodic Task Thread - -1 - 0.0 0.000 0:0.000 false true -1 GC task thread#0 (ParallelGC) - -1 - 0.0 0.000 0:0.000 false true -1 C2 CompilerThread0 - -1 - 0.0 0.000 0:0.296 false true -1 Service Thread - -1 - 0.0 0.000 0:0.000 false true -1 C2 CompilerThread1 - -1 - 0.0 0.000 0:0.218 false true -1 GC task thread#1 (ParallelGC) - -1 - 0.0 0.000 0:0.000 false true -1 C1 CompilerThread3 - -1 - 0.0 0.000 0:0.609 false true -1 VM Thread - -1 - 0.0 0.000 0:0.031 false true -1 GC task thread#2 (ParallelGC) - -1 - 0.0 0.000 0:0.000 false true -1 GC task thread#3 (ParallelGC) - -1 - 0.0 0.000 0:0.000 false true -1 GC task thread#5 (ParallelGC) - -1 - 0.0 0.000 0:0.000 false true -1 GC task thread#4 (ParallelGC) - -1 - 0.0 0.000 0:0.000 false true
例如:thread 1会打印线程ID 1的栈,通常是main函数的线程。
[arthas@28868]$ thread 1 | grep ‘main(‘ at arthas.ArthasTest.main(ArthasTest.java:15)
3. jad 反编译类信息
[arthas@28868]$ jad arthas.ArthasTest ClassLoader: +-sun.misc.Launcher$AppClassLoader@18b4aac2 +-sun.misc.Launcher$ExtClassLoader@3af87f7 Location: /E:/xiangmu/MvnPro/target/classes/ /* * Decompiled with CFR. */ package arthas; public class ArthasTest { public static void main(String[] args) { System.out.println(Thread.currentThread().getName()); String test = System.getProperty("test"); while (true) { String test2; if ((test2 = System.getProperty("test")) == null || test2.equals(test)) { continue; } System.out.println(test2); test = test2; } } }
4. 开启保存日志
options 查看配置,相当于查看arthas内置的全局配置属性
options save-result true 开启保存日志。会保存到{user}/logs\arthas-cache/result.log 中
5.退出
如果只是退出当前的连接,可以用quit或者exit命令。Attach到目标进程上的arthas还会继续运行,端口会保持开放,下次连接时可以直接连接上。
如果想完全退出arthas,可以执行stop命令。
sysenv 查看JVM的环境变量
sysprop 查看JVM的所有的系统属性
sysprop java.version 查看单个系统的属性
sysprop user.country US 修改user.country 属性的值为US
比如上面修改 test 属性为 testValue,修改之后会被程序System.getProperty(key) 获取到
[arthas@28868]$ sysprop test testValue Successfully changed the system property. KEY VALUE ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- test testValue [arthas@28868]$ sysprop test KEY VALUE ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- test testValue
我们到IDEA查看main线程打出的信息:testValue
比如如下简单的Controller和Service:
controller:
package com.xm.ggn.controller; import com.xm.ggn.service.common.MessageService2; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; @RestController public class TestController { @Value("${test:defaultValue}") private String test; @RequestMapping("test") public String test() { return test; } @Autowired private MessageService2 messageService; @RequestMapping("tx1") public void tx1() { messageService.tx1(); } @RequestMapping("tx2") public void tx2() { messageService.tx2(); } @RequestMapping("tx4") public void tx4() { messageService.tx4(); } }
service:
package com.xm.ggn.service.common; public interface MessageService2 { void tx1(); void tx2(); void tx3(); void tx4(); }
serviceimpl:
package com.xm.ggn.service.common.impl; import com.xm.ggn.bean.common.Message; import com.xm.ggn.mapper.common.MessageMapper; import com.xm.ggn.service.common.MessageService2; import org.springframework.aop.framework.AopContext; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import javax.transaction.Transactional; @Service //@Transactional public class MessageService2Impl implements MessageService2 { @Autowired private MessageMapper messageMapper; @Override @Transactional public void tx1() { // 调用tx3方法会回滚,因为这里有事务直接,会走代理,且tx3方法会加入本事务 tx3(); } @Override public void tx2() { try { Thread.sleep(1 * 1000); } catch (InterruptedException e) { e.printStackTrace(); } // 调用tx3方法不会回滚,因为这里没有事务。即使tx3有事务也不会走代理,因为通过内部方法调用不会走代理。解决办法查看tx4 方法 tx3(); } @Override @Transactional public void tx3() { Message message = new Message(); message.setTitle("tx3"); messageMapper.insert(message); int i = 1 / 0; } // 这样进行方法内部调用AOP会生效,主启动类加@EnableAspectJAutoProxy(proxyTargetClass = true, exposeProxy = true) 注解 @Override public void tx4() { MessageService2 messageService = (MessageService2) AopContext.currentProxy(); // 这样调用tx3会进行回滚,走的是代理类的方法 messageService.tx3(); } }
启动应用后启动arthas并且监视对应进程
1. 搜索:模糊搜索
[arthas@13232]$ sc *.MessageService2
com.xm.ggn.service.common.MessageService2
com.xm.ggn.service.common.impl.MessageService2Impl
com.xm.ggn.service.common.impl.MessageService2Impl$$EnhancerBySpringCGLIB$$7fa3a2fc
Affect(row-cnt:3) cost in 56 ms.
如果查看加载的所有类,可以用:
sc *
2. 反编译查看AOP增强的类
[arthas@13232]$ jad com.xm.ggn.service.common.impl.MessageService2Impl$$EnhancerBySpringCGLIB$$7fa3a2fc ClassLoader: +-sun.misc.Launcher$AppClassLoader@18b4aac2 +-sun.misc.Launcher$ExtClassLoader@3c22fc4c Location: /E:/xiangmu/bs-media/media-server/target/classes/ /* * Decompiled with CFR. * * Could not load the following classes: * com.xm.ggn.service.common.impl.MessageService2Impl */ package com.xm.ggn.service.common.impl; import com.xm.ggn.service.common.impl.MessageService2Impl; import java.lang.reflect.Method; import org.aopalliance.aop.Advice; import org.springframework.aop.Advisor; import org.springframework.aop.SpringProxy; import org.springframework.aop.TargetClassAware; import org.springframework.aop.TargetSource; import org.springframework.aop.framework.Advised; import org.springframework.aop.framework.AopConfigException; import org.springframework.cglib.core.ReflectUtils; import org.springframework.cglib.core.Signature; import org.springframework.cglib.proxy.Callback; import org.springframework.cglib.proxy.Dispatcher; import org.springframework.cglib.proxy.Factory; import org.springframework.cglib.proxy.MethodInterceptor; import org.springframework.cglib.proxy.MethodProxy; import org.springframework.cglib.proxy.NoOp; public class MessageService2Impl$$EnhancerBySpringCGLIB$$7fa3a2fc extends MessageService2Impl implements SpringProxy, Advised, Factory { private boolean CGLIB$BOUND; public static Object CGLIB$FACTORY_DATA; ... }
比如检测:com.xm.ggn.controller.TestController 类的所有方法,如下:
[arthas@13232]$ trace com.xm.ggn.controller.TestController * Press Q or Ctrl+C to abort. Affect(class count: 1 , method count: 5) cost in 93 ms, listenerId: 1 `---ts=2021-01-12 21:15:57;thread_name=http-nio-8088-exec-1;id=108;is_daemon=true;priority=5;TCCL=org.springframework.boot.web.embedded.tomcat.TomcatEmbeddedWebappClassLoader@3ee39a1c `---[45.0785ms] com.xm.ggn.controller.TestController:tx4() [throws Exception] +---[44.0299ms] com.xm.ggn.service.common.MessageService2:tx4() #40 [throws Exception] `---throw:java.lang.ArithmeticException #39 [/ by zero]
trace还有好几个参数可以过滤以及支持检测多个类的多个方法以及根据时长过滤等
[arthas@19792]$ watch com.xm.ggn.controller.TestController * "{params,returnObj}" Press Q or Ctrl+C to abort. Affect(class count: 1 , method count: 5) cost in 79 ms, listenerId: 3 method=com.xm.ggn.controller.TestController.test location=AtExit ts=2021-01-12 21:32:16; [cost=0.0674ms] result=@ArrayList[ @Object[][isEmpty=true;size=0], @String[defaultValue], ]
调用一次test 方法之后结果如上。可以看到参数为空,返回值是一个String值为"defaultValue"。
这个结果可能不太明显,增加一个测试用例:
(1)Controller增加一个方法:
@RequestMapping("testMap") public Map test(String key1, String key2) { HashMap<String, Object> stringObjectHashMap = new HashMap<>(); stringObjectHashMap.put(key1, key1); stringObjectHashMap.put(key2, key2); return stringObjectHashMap; }
(2)arthas检测: -x 指定输出结果的属性遍历深度,默认为 1
[arthas@27848]$ watch com.xm.ggn.controller.TestController * "{params,returnObj}" -x 3 Press Q or Ctrl+C to abort. Affect(class count: 1 , method count: 6) cost in 38 ms, listenerId: 5
(3)访问:
http://localhost:8088/testMap?key1=111&key2=222
(4)arthas控制台输出
method=com.xm.ggn.controller.TestController.test location=AtExit ts=2021-01-12 21:40:26; [cost=0.0351ms] result=@ArrayList[ @Object[][ @String[111], @String[222], ], @HashMap[ @String[111]:@String[111], @String[222]:@String[222], ], ]
补充:第一次运行jar包选择进程进入的时候会自动从互联网下载几个依赖包,自动放在 ${user}/.arthas/lib。如果是离线环境可以将lib下面的包传到离线的服务器,启动的时候指定路径:如下:
java -jar arthas-boot.jar --arthas-home C:\Users\qlq\Desktop\plaintools\arthas\lib\3.4.5\arthas
--arthas-home 指定依赖包的路径
补充:Arthas目前支持Web Console,用户在attach成功之后,可以直接访问:http://127.0.0.1:3658/。默认情况下,arthas只listen 127.0.0.1,所以如果想从远程连接,则可以使用 --target-ip
参数指定listen的IP,更多参考-h
的帮助说明。
标签:mis 线程id @Value manager map sso interrupt group net
原文地址:https://www.cnblogs.com/qlqwjy/p/14269457.html