├── src ├── main │ ├── resources │ │ ├── custom-last.properties │ │ ├── custom-first.properties │ │ ├── arthas command.png │ │ ├── arthas command.xmind │ │ ├── META-INF │ │ │ └── spring.factories │ │ ├── application.properties │ │ ├── data.sql │ │ └── schema.sql │ └── java │ │ └── com │ │ └── wangji92 │ │ └── arthas │ │ └── plugin │ │ └── demo │ │ ├── controller │ │ ├── NotLoaderClass.java │ │ ├── TestGeneratesClazz.java │ │ ├── LoggerDemo.java │ │ ├── User.java │ │ ├── TestEnum.java │ │ ├── CityRestController.java │ │ ├── TestLifeService.java │ │ ├── OuterClass.java │ │ ├── StaticTest.java │ │ └── CommonController.java │ │ ├── service │ │ ├── ArthasTestService.java │ │ └── impl │ │ │ └── ArthasTestServiceImpl.java │ │ ├── ArthasPluginDemoApplication.java │ │ ├── common │ │ ├── config │ │ │ ├── TestLifeConfiguration.java │ │ │ └── WebConfig.java │ │ ├── ApplicationContextProvider.java │ │ ├── environment │ │ │ ├── CustomLastEnvironmentPostProcessor.java │ │ │ ├── CustomFirstEnvironmentPostProcessor.java │ │ │ └── PrintAllSpringEnvironmentPropertiesActuator.java │ │ ├── InvokeStaticCommandLine.java │ │ └── profile │ │ │ └── HotCode.java │ │ ├── mapper │ │ └── CityMapper.java │ │ └── domain │ │ └── City.java └── test │ └── java │ └── com │ └── wangji92 │ └── arthas │ └── plugin │ └── demo │ ├── ArthasPluginDemoApplicationTests.java │ └── SpringAnnotation.java ├── start-async-profile.sh ├── .mvn └── wrapper │ ├── maven-wrapper.jar │ ├── maven-wrapper.properties │ └── MavenWrapperDownloader.java ├── start.sh ├── .gitignore ├── README.md ├── pom.xml ├── mvnw.cmd └── mvnw /src/main/resources/custom-last.properties: -------------------------------------------------------------------------------- 1 | custom.name = Custom Environment Last Name 2 | -------------------------------------------------------------------------------- /src/main/resources/custom-first.properties: -------------------------------------------------------------------------------- 1 | custom.name = Custom Environment first Name 2 | -------------------------------------------------------------------------------- /start-async-profile.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh -x 2 | jdb -connect com.sun.jdi.SocketAttach:port=5005,hostname=127.0.0.1 -------------------------------------------------------------------------------- /.mvn/wrapper/maven-wrapper.jar: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WangJi92/arthas-plugin-demo/HEAD/.mvn/wrapper/maven-wrapper.jar -------------------------------------------------------------------------------- /src/main/resources/arthas command.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WangJi92/arthas-plugin-demo/HEAD/src/main/resources/arthas command.png -------------------------------------------------------------------------------- /src/main/resources/arthas command.xmind: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/WangJi92/arthas-plugin-demo/HEAD/src/main/resources/arthas command.xmind -------------------------------------------------------------------------------- /.mvn/wrapper/maven-wrapper.properties: -------------------------------------------------------------------------------- 1 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.6.3/apache-maven-3.6.3-bin.zip 2 | wrapperUrl=https://repo.maven.apache.org/maven2/io/takari/maven-wrapper/0.5.6/maven-wrapper-0.5.6.jar 3 | -------------------------------------------------------------------------------- /src/main/resources/META-INF/spring.factories: -------------------------------------------------------------------------------- 1 | org.springframework.boot.env.EnvironmentPostProcessor=\ 2 | com.wangji92.arthas.plugin.demo.common.environment.CustomFirstEnvironmentPostProcessor,\ 3 | com.wangji92.arthas.plugin.demo.common.environment.CustomLastEnvironmentPostProcessor -------------------------------------------------------------------------------- /start.sh: -------------------------------------------------------------------------------- 1 | #!/bin/sh -x 2 | dir=$(cd `dirname $0`;pwd) 3 | echo $dir 4 | mvn clean package -Dmaven.test.skip=true && \ 5 | java -agentlib:jdwp=transport=dt_socket,address=5005,server=y,suspend=y \ 6 | -jar $dir/target/arthas-demo.jar 7 | 8 | 9 | # 参考 http://kail.xyz/Troubleshooting/docs/Arthas/Case/Slow-Start/ -------------------------------------------------------------------------------- /src/main/java/com/wangji92/arthas/plugin/demo/controller/NotLoaderClass.java: -------------------------------------------------------------------------------- 1 | package com.wangji92.arthas.plugin.demo.controller; 2 | 3 | import lombok.extern.slf4j.Slf4j; 4 | 5 | /** 6 | * @author 汪小哥 7 | * @date 15-08-2020 8 | */ 9 | @Slf4j 10 | public class NotLoaderClass { 11 | public static String NO_LOAD = "not load"; 12 | } 13 | -------------------------------------------------------------------------------- /src/test/java/com/wangji92/arthas/plugin/demo/ArthasPluginDemoApplicationTests.java: -------------------------------------------------------------------------------- 1 | package com.wangji92.arthas.plugin.demo; 2 | 3 | import org.junit.jupiter.api.Test; 4 | import org.springframework.boot.test.context.SpringBootTest; 5 | 6 | @SpringBootTest 7 | class ArthasPluginDemoApplicationTests { 8 | 9 | @Test 10 | void contextLoads() { 11 | } 12 | 13 | } 14 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | HELP.md 2 | target/ 3 | !.mvn/wrapper/maven-wrapper.jar 4 | !**/src/main/** 5 | !**/src/test/** 6 | 7 | ### STS ### 8 | .apt_generated 9 | .classpath 10 | .factorypath 11 | .project 12 | .settings 13 | .springBeans 14 | .sts4-cache 15 | 16 | ### IntelliJ IDEA ### 17 | .idea 18 | *.iws 19 | *.iml 20 | *.ipr 21 | 22 | ### NetBeans ### 23 | /nbproject/private/ 24 | /nbbuild/ 25 | /dist/ 26 | /nbdist/ 27 | /.nb-gradle/ 28 | build/ 29 | 30 | ### VS Code ### 31 | .vscode/ 32 | -------------------------------------------------------------------------------- /src/main/java/com/wangji92/arthas/plugin/demo/service/ArthasTestService.java: -------------------------------------------------------------------------------- 1 | package com.wangji92.arthas.plugin.demo.service; 2 | 3 | /** 4 | * 测试服务、方便观察多层 trace -E 5 | * @author 汪小哥 6 | * @date 28-03-2020 7 | */ 8 | public interface ArthasTestService { 9 | 10 | /** 11 | * trace -E 效果 12 | * @param name 13 | * @return 14 | */ 15 | String doTraceE(String name); 16 | 17 | /** 18 | * 没有捕获异常 19 | * @param number 20 | */ 21 | void traceException(int number); 22 | } 23 | -------------------------------------------------------------------------------- /src/main/java/com/wangji92/arthas/plugin/demo/ArthasPluginDemoApplication.java: -------------------------------------------------------------------------------- 1 | package com.wangji92.arthas.plugin.demo; 2 | 3 | import org.springframework.boot.SpringApplication; 4 | import org.springframework.boot.autoconfigure.SpringBootApplication; 5 | import org.springframework.scheduling.annotation.EnableScheduling; 6 | 7 | @SpringBootApplication 8 | @EnableScheduling 9 | public class ArthasPluginDemoApplication { 10 | 11 | public static void main(String[] args) { 12 | SpringApplication.run(ArthasPluginDemoApplication.class, args); 13 | } 14 | 15 | } 16 | -------------------------------------------------------------------------------- /src/main/java/com/wangji92/arthas/plugin/demo/controller/TestGeneratesClazz.java: -------------------------------------------------------------------------------- 1 | package com.wangji92.arthas.plugin.demo.controller; 2 | 3 | import lombok.Data; 4 | 5 | /** 6 | *
intro
7 | *
8 | * {@code
9 | * //code example
10 | * }
11 | *
12 | *
13 | * @author wangji
14 | * @date 2024/5/19 01:03
15 | */
16 | @Data
17 | public class TestGeneratesClazzintro
18 | *
19 | * {@code
20 | * //code example
21 | * }
22 | *
23 | *
24 | * @author wangji
25 | * @date 2024/11/15 21:50
26 | */
27 | @Slf4j
28 | @Component
29 | public class PrintAllSpringEnvironmentPropertiesActuator implements CommandLineRunner, EnvironmentAware {
30 |
31 | private Environment environment;
32 |
33 | @Override
34 | public void run(String... args) throws Exception {
35 | try {
36 | printEnvironmentProperties();
37 | } catch (Exception e) {
38 | log.error("print env error", e);
39 | }
40 | }
41 |
42 | private void printEnvironmentProperties() {
43 | List74 | * 备注插件不支持 ,需要记住小知识点 75 | *
76 | * ognl -x 3 '@com.wangji92.arthas.plugin.demo.controller.StaticTest@invokeClass(@com.wangji92.arthas.plugin.demo.controller.StaticTest@class)' -c 482503f0
77 | * ognl -x 3 '@com.wangji92.arthas.plugin.demo.controller.StaticTest@invokeClass(@java.lang.Object@class)' -c 316bc132
78 | *
79 | * @param classN
80 | * @return
81 | */
82 | public static String invokeClass(Class classN) {
83 | if (classN == null) {
84 | return "";
85 | }
86 | return classN.getName();
87 | }
88 |
89 | /**
90 | * 对于class类型的参数进行了增强处理
91 | * ognl -x 3 '@com.wangji92.arthas.plugin.demo.controller.StaticTest@invokeClass1(@com.wangji92.arthas.plugin.demo.controller.User@class)' -c 316bc132
92 | * @param classN
93 | * @return
94 | */
95 | public static String invokeClass1(Class
108 | * ognl -x 3 '@com.wangji92.arthas.plugin.demo.controller.StaticTest@invokeStaticMethodArray(new java.lang.String[]{"wangji"})' -c 316bc132
109 | * ognl -x 3 '#array=new java.lang.String[]{"wangji"},@com.wangji92.arthas.plugin.demo.controller.StaticTest@invokeStaticMethodArray(#array)' -c 316bc132
110 | *
111 | * @param arrays
112 | * @return
113 | */
114 | public static String invokeStaticMethodArray(String[] arrays) {
115 | if (arrays == null) {
116 | return "";
117 | }
118 | return Arrays.toString(arrays);
119 | }
120 |
121 |
122 | /**
123 | * 调用静态方法 参数为list
124 | * 复杂的参数场景 #listObject={} ,#mapObject= #{"key","value"} #array=new java.lang.String[]{"1"}
125 | *
126 | * ognl -x 3 '@com.wangji92.arthas.plugin.demo.controller.StaticTest@invokeStaticMethodParamList({"wangji"})' -c 316bc132
127 | *
128 | * @param list
129 | * @return
130 | */
131 | public static String invokeStaticMethodParamList(List
157 | * ognl -x 3 '@com.wangji92.arthas.plugin.demo.controller.StaticTest@invokeStaticMethodParamObjUser(new com.wangji92.arthas.plugin.demo.controller.User("wangji",27L))' -c e374b99
158 | * ognl -x 3 '#user=new com.wangji92.arthas.plugin.demo.controller.User(),#user.setName("wangji"),#user.setAge(27L),@com.wangji92.arthas.plugin.demo.controller.StaticTest@invokeStaticMethodParamObjUser(#user)' -c e374b99
159 | * 调用静态方法 是一个对象
160 | *
161 | * @param user
162 | * @return
163 | */
164 | public static String invokeStaticMethodParamObjUser(User user) {
165 | if (user == null) {
166 | return "EMPTY";
167 | }
168 | return user.toString();
169 | }
170 |
171 | /**
172 | * 复杂的参数场景 #listObject={} ,#mapObject= #{"key","value"} #array=new java.lang.String[]{"1"}
173 | *
174 | * ognl -x 3 '#user=new com.wangji92.arthas.plugin.demo.controller.User(),#user.setName("wangji"),#user.setAge(27L),@com.wangji92.arthas.plugin.demo.controller.StaticTest@invokeStaticMethodParamObjListUser(0,{#user,#user})' -c e374b99
175 | *
176 | * @param number
177 | * @param names
178 | * @return
179 | */
180 | public static String invokeStaticMethodParamObjListUser(Integer number, List
226 | * 记录时间隧道,重新触发一次 tt -t com.wangji92.arthas.plugin.demo.controller.CommonController getRandomInteger -n 5 tt -p -i
227 | * 1000
228 | *
229 | * @return
230 | */
231 | @RequestMapping("/getRandomInteger")
232 | @ResponseBody
233 | public Integer getRandomInteger() {
234 | return new Random().nextInt(1000);
235 |
236 | }
237 |
238 | /**
239 | * use trace -E trace -E
240 | * com.wangji92.arthas.plugin.demo.controller.CommonController|com.wangji92.arthas.plugin.demo.service.ArthasTestService
241 | * traceE|doTraceE -n 5
242 | *
243 | * ##包含jdk的调用 trace -E
244 | * com.wangji92.arthas.plugin.demo.controller.CommonController|com.wangji92.arthas.plugin.demo.service.ArthasTestService
245 | * traceE|doTraceE -n 5 --skipJDKMethod false
246 | *
247 | * @param name
248 | * @return
249 | */
250 | @RequestMapping("/trace/{name}")
251 | @ResponseBody
252 | public String traceE(@PathVariable String name) {
253 | if (StringUtils.isEmpty(name)) {
254 | name = "汪小哥";
255 | } else {
256 | name = name + "汪小哥";
257 | }
258 | return arthasTestService.doTraceE(name);
259 | }
260 |
261 | /**
262 | * 排查异常场景 trace com.wangji92.arthas.plugin.demo.controller.CommonController traceException -n 5 watch
263 | * com.wangji92.arthas.plugin.demo.controller.CommonController traceException '{params,returnObj,throwExp}' -n 5 -x
264 | * 3
265 | *
266 | * @return
267 | */
268 | @RequestMapping("traceException")
269 | @ResponseBody
270 | public String traceException() {
271 | arthasTestService.traceException(1);
272 | return "ok";
273 | }
274 |
275 | /**
276 | * 环境变量优先级问题排查 目前只支持获取静态static spring context 获取所有的环境变量 按照优先级排序 ognl -x 3
277 | * '#springContext=@com.wangji92.arthas.plugin.demo.common.ApplicationContextProvider@context,#allProperties={},#standardServletEnvironment=#propertySourceIterator=#springContext.getEnvironment(),#propertySourceIterator=#standardServletEnvironment.getPropertySources().iterator(),#propertySourceIterator.{#key=#this.getName(),#allProperties.add("
278 | * "),#allProperties.add("------------------------- name:"+#key),#this.getSource() instanceof java.util.Map
279 | * ?#this.getSource().entrySet().iterator.{#key=#this.key,#allProperties.add(#key+"="+#standardServletEnvironment.getProperty(#key))}:#{}},#allProperties'
280 | * -c e374b99
281 | *
282 | * 选中 custom.name 获取当前的变量的信息 ognl -x 3
283 | * '#springContext=@com.wangji92.arthas.plugin.demo.common.ApplicationContextProvider@context,#springContext.getEnvironment().getProperty("custom.name")'
284 | * -c e374b99
285 | *
286 | * @return
287 | */
288 | @RequestMapping("environmentPriority")
289 | @ResponseBody
290 | public String environmentPriority() {
291 | return applicationContext.getEnvironment().getProperty("custom.name");
292 | }
293 |
294 | /**
295 | * 复杂参数调用 场景 static spring context ognl -x 3 '#user=new
296 | * com.wangji92.arthas.plugin.demo.controller.User(),#user.setName("wangji"),#user.setAge(27L),#springContext=@com.wangji92.arthas.plugin.demo.common.ApplicationContextProvider@context,#springContext.getBean("commonController").complexParameterCall(#{"wangji":#user})'
297 | * -c e374b99
298 | *
299 | * watch get spring context 备注 需要调用一次方法 watch -x 3 -n 1 org.springframework.web.servlet.DispatcherServlet doDispatch
300 | * '#user=new
301 | * com.wangji92.arthas.plugin.demo.controller.User(),#user.setName("wangji"),#user.setAge(27L),@org.springframework.web.context.support.WebApplicationContextUtils@getWebApplicationContext(params[0].getServletContext()).getBean("commonController").complexParameterCall(#{"wangji":#user})'
302 | *
303 | * tt get spring context ,only first get time index ok tt -w '#user=new
304 | * com.wangji92.arthas.plugin.demo.controller.User(),#user.setName("wangji"),#user.setAge(27L),target.getApplicationContext().getBean("commonController").complexParameterCall(#{"wangji":#user})'
305 | * -x 3 -i 1000
306 | *
307 | * @return
308 | */
309 | @RequestMapping("complexParameterCall")
310 | @ResponseBody
311 | public String complexParameterCall(@RequestBody Map
324 | * watch com.wangji92.arthas.plugin.demo.controller.CommonController *
325 | * '{params,returnObj,throwExp,target.arthasTestService}' -n 5 -x 3 '1==1'
326 | *
327 | * 2、触发一下这个类的某个方法的调用 eg: 比如这里调用这个 http://localhost:8080/watchField 3、即可查看到具体的信息
328 | *
329 | * @return
330 | */
331 | @RequestMapping("watchField")
332 | @ResponseBody
333 | public String watchField() {
334 | return StaticTest.getInvokeStaticName();
335 | }
336 |
337 | /**
338 | * 调用非静态的方法才可以在watch 的时候获取非静态的字段 watch com.wangji92.arthas.plugin.demo.controller.StaticTest *
339 | * '{params,returnObj,throwExp,target.filedValue}' -n 5 -x 3 'method.initMethod(),method.constructor!=null ||
340 | * !@java.lang.reflect.Modifier@isStatic(method.method.getModifiers())'
341 | *
342 | * @return
343 | */
344 | @RequestMapping("watchNoStaticField")
345 | @ResponseBody
346 | public String watchNoStaticField() {
347 | return staticTest.getFieldValue();
348 | }
349 |
350 | @RequestMapping("AnonymousClass")
351 | @ResponseBody
352 | public String anonymousClass() {
353 | Runnable x = new Runnable() {
354 |
355 | @Override
356 | public void run() {
357 | log.info(this.getClass().getName());
358 | }
359 | };
360 | x.run();
361 | return "ok";
362 | }
363 |
364 | @RequestMapping("innerAnonymousClass")
365 | @ResponseBody
366 | public String innerAnonymousClass() {
367 | OuterClass.InnerClass innerClass = new OuterClass.InnerClass();
368 | innerClass.anonymousClassRun();
369 | innerClass.getInnerAge();
370 | OuterClass.InnerClass.InnerInnerClass innerInnerClass = innerClass.new InnerInnerClass();
371 | innerInnerClass.getInnerInnerAge();
372 | innerInnerClass.anonymousInnerInnerClassRun();
373 | return "ok";
374 | }
375 |
376 | /**
377 | * vmtool -x 3 --action getInstances --className com.wangji92.arthas.plugin.demo.controller.CommonController
378 | * --express 'instances[0].testEnum(@com.wangji92.arthas.plugin.demo.controller.TestEnum@COMMON_1)' -c 59a6bc53
379 | * 先测试一下枚举
380 | *
381 | * @param testEnum
382 | * @return
383 | */
384 | @RequestMapping("testEnum")
385 | @ResponseBody
386 | public String testEnum(TestEnum testEnum) {
387 | if (testEnum != null) {
388 | return testEnum.getName();
389 | }
390 | return "ok";
391 | }
392 |
393 | /**
394 | * check head
395 | * @return
396 | */
397 | @RequestMapping("checkHead")
398 | @ResponseBody
399 | public String checkHead() {
400 |
401 | return "ok";
402 | }
403 |
404 | public Object testParam(MonthDay param){
405 | return param;
406 | }
407 |
408 | public Object testParam2(Pattern param){
409 | return param;
410 | }
411 |
412 | public Object testParam3(Date param){
413 | return param;
414 | }
415 | public Object testParam3(AtomicLong param){
416 | return param;
417 | }
418 |
419 |
420 | }
421 |
--------------------------------------------------------------------------------