├── .gitignore
├── README.md
├── pom.xml
├── sandbox-module
├── pom.xml
└── src
│ └── main
│ └── java
│ └── com
│ └── online
│ └── test
│ └── MySandBoxModule.java
└── springboot-demo
├── pom.xml
└── src
└── main
├── java
└── com
│ └── online
│ ├── MyApp.java
│ └── test
│ └── TestAdd.java
└── resources
├── application.yml
└── logback-spring.xml
/.gitignore:
--------------------------------------------------------------------------------
1 | # Created by .ignore support plugin (hsz.mobi)
2 |
3 | .gradle
4 | /local.properties
5 | /.idea/workspace.xml
6 | /.idea/libraries
7 | .DS_Store
8 | /build
9 | /captures
10 |
11 | # Built application files
12 | *.apk
13 | *.ap_
14 |
15 | # Files for the Dalvik VM
16 | *.dex
17 |
18 | # Java class files
19 | *.class
20 |
21 |
22 | # Generated files
23 | bin/
24 | gen/
25 |
26 | # Gradle files
27 | .gradle/
28 | build/
29 | */target
30 | /target
31 |
32 | # Local configuration file (sdk path, etc)
33 | local.properties
34 |
35 | # Proguard folder generated by Eclipse
36 | proguard/
37 |
38 | # Log Files
39 | *.log
40 |
41 | # Others
42 | .idea/
43 | *.iml
44 |
45 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Arthas和jvm-sandbox对比简单使用
2 | https://www.cnblogs.com/ttzzyy/p/11414051.html
3 | # 1 阿里在线分析诊断工具Arthas(阿尔萨斯)
4 |
5 | > 参考: https://alibaba.github.io/arthas/
6 | >
7 | > 参考: https://github.com/alibaba/arthas/blob/master/README_CN.md
8 |
9 | 
10 |
11 | # 2 阿里在线分析诊断工具Jvm-Sandbox(JVM沙盒)
12 |
13 | > 参考: https://github.com/alibaba/jvm-sandbox
14 |
15 | 
16 |
17 | 
18 |
19 | # 3 Arthas与Jvm-Sandbox比较
20 |
21 | > Arthas就像是一个剑冢,如果你希望得到一把宝剑就进去拿就好了! 它提供了各式各样的命令可以满足你的各项业务需求,上手成本较高。
22 |
23 | > Jvm-Sandbox就像是一个剑炉,其提供了Module的概念,每个Module都是一个AOP的实例,也就是一把剑,怎么样锻造取决于工匠,也就是你啦!它提供了模型,具体实现需要你自己编写,灵活性更高。上手成本相对较低
24 |
25 | - 下面将通过日常碰到的需要添加日志的需求,对两个开源项目的进行体验。
26 |
27 | # 4 添加日志案例
28 |
29 | > 项目地址: https://github.com/70416450/Online-debugging-demo
30 |
31 | - 针对springboot-demo项目
32 |
33 | 1. 使用 mvn clean install命令编译
34 | 2. 上传springboot-demo-1.0-SNAPSHOT.jar包到服务器上
35 | 3. 使用java -jar springboot-demo-1.0-SNAPSHOT.jar启动项目,看见如下效果
36 | 4. 
37 |
38 | ## 4.1 Jvm-Sandbox体验
39 |
40 | ### 4.1.1 下载解压
41 |
42 | ```
43 | # 下载最新版本的JVM-SANDBOX
44 | wget http://ompc.oss-cn-hangzhou.aliyuncs.com/jvm-sandbox/release/sandbox-stable-bin.zip
45 |
46 | # 解压
47 | unzip sandbox-stable-bin.zip
48 | ```
49 |
50 | ### 4.1.2 挂载目标应用
51 |
52 | ```
53 | # 进入沙箱执行脚本
54 | cd sandbox/bin
55 |
56 | # 常用命令!!!
57 | # 目标JVM进程93726(使用jps命令查看)
58 | ./sandbox.sh -p 93726
59 | #卸载沙箱
60 | ./sandbox.sh -p 93726 -S
61 | #查询沙箱
62 | ./sandbox.sh -p 93726 -l
63 | #刷新沙箱
64 | ./sandbox.sh -p 93726 -F
65 | #使用自定义module执行(my-sandbox-module:自定义的module名字,addLog自定义切入方法名字)
66 | ./sandbox.sh -p 93726 -d 'my-sandbox-module/addLog'
67 |
68 | #日志配置及查看
69 | #配置文件在 /sandbox/cfg/sandbox-logback.xml
70 | #默认日志路径 ~/logs/sandbox/sandbox.log
71 | ```
72 |
73 | 
74 |
75 | - 针对springboot-demo项目
76 |
77 | 1. 使用 mvn clean compile assembly:single 打包,上传至sandbox/sandbox-module目录下
78 | 2. 
79 | 3. 回到bin目录,
80 | - ./sandbox.sh -p 93726 -S 停止沙箱
81 | - ./sandbox.sh -p 93726 -F 刷新沙箱
82 | - ./sandbox.sh -p 93726 -l 查看沙箱
83 | - ./sandbox.sh -p 93726 -d 'my-sandbox-module/addLog' 使用自定义module执行(my-sandbox-module:自定义的module名字,addLog自定义切入方法名字)
84 | 4. 
85 | 5. 切换到springboot-demo项目日志查看
86 | 6. 
87 |
88 |
89 |
90 | ## 4.2 Arthas体验
91 |
92 | - 下载idea插件 Alibaba Cloud Toolkit https://plugins.jetbrains.com/plugin/11386-alibaba-cloud-toolkit/
93 |
94 | - 添加服务器地址并打开Arthas监控
95 |
96 | - 
97 |
98 | - 输入数字选择对应的进程
99 |
100 | - 
101 |
102 | - 启动成功
103 |
104 | - 
105 |
106 | - **通过sc命令查找需要修改的class的ClassLoader**
107 |
108 | - ```
109 | sc -d *TestAdd | grep classLoaderHash
110 | ```
111 |
112 | - 
113 |
114 | - 修改TestAdd
115 |
116 | - 
117 |
118 | - 
119 |
120 | - 将重新编译的class文件上传至服务器指定目录
121 |
122 | - 
123 |
124 | - 
125 |
126 | - **再使用redefine命令重新加载新编译好的TestAdd.class**(注意hash码和需要替换的类路径)
127 |
128 | - ```
129 | redefine -c 439f5b3d /usr/local/src/jvm-sandbox/test/TestAdd.class
130 | ```
131 |
132 | - 
133 |
134 | - **注意点:**
135 |
136 | - **重启项目可以恢复**
137 | - **不允许新增加field/method**
138 | - **正在跑的函数,没有退出不能生效**
139 |
140 |
141 |
142 |
143 |
144 |
--------------------------------------------------------------------------------
/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 | 4.0.0
6 |
7 | com.online
8 | demo
9 | pom
10 | 1.0-SNAPSHOT
11 |
12 | springboot-demo
13 | sandbox-module
14 |
15 |
16 |
17 | org.springframework.boot
18 | spring-boot-starter-parent
19 | 2.1.6.RELEASE
20 |
21 |
22 |
23 |
24 |
25 | org.projectlombok
26 | lombok
27 | true
28 |
29 |
30 |
31 | junit
32 | junit
33 | test
34 |
35 |
36 |
37 | org.slf4j
38 | slf4j-api
39 |
40 |
41 | ch.qos.logback
42 | logback-core
43 |
44 |
45 | ch.qos.logback
46 | logback-classic
47 |
48 |
49 |
50 | org.springframework.boot
51 | spring-boot-starter-aop
52 |
53 |
54 |
55 |
--------------------------------------------------------------------------------
/sandbox-module/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 | demo
7 | com.online
8 | 1.0-SNAPSHOT
9 |
10 | 4.0.0
11 |
12 | sandbox-module
13 |
14 |
15 | com.alibaba.jvm.sandbox
16 | sandbox-api
17 | 1.2.0
18 |
19 |
20 | org.kohsuke.metainf-services
21 | metainf-services
22 | 1.7
23 |
24 |
25 |
26 |
27 |
28 |
29 | maven-assembly-plugin
30 |
31 |
32 |
33 |
34 |
35 |
36 |
37 | jar-with-dependencies
38 |
39 |
40 |
41 |
42 | make-assembly
43 | package
44 |
45 | single
46 |
47 |
48 |
49 |
50 |
51 |
52 |
53 |
54 |
--------------------------------------------------------------------------------
/sandbox-module/src/main/java/com/online/test/MySandBoxModule.java:
--------------------------------------------------------------------------------
1 | package com.online.test;
2 |
3 | import com.alibaba.jvm.sandbox.api.Information;
4 | import com.alibaba.jvm.sandbox.api.Module;
5 | import com.alibaba.jvm.sandbox.api.annotation.Command;
6 | import com.alibaba.jvm.sandbox.api.listener.ext.Advice;
7 | import com.alibaba.jvm.sandbox.api.listener.ext.AdviceListener;
8 | import com.alibaba.jvm.sandbox.api.listener.ext.EventWatchBuilder;
9 | import com.alibaba.jvm.sandbox.api.resource.ModuleEventWatcher;
10 | import lombok.extern.slf4j.Slf4j;
11 | import org.kohsuke.MetaInfServices;
12 |
13 | import javax.annotation.Resource;
14 |
15 | @MetaInfServices(Module.class)
16 | @Information(id = "my-sandbox-module")// 模块名,在指定挂载进程后通过-d指定模块,配合@Command注解来唯一确定方法
17 | @Slf4j
18 | public class MySandBoxModule implements Module {
19 |
20 | @Resource
21 | private ModuleEventWatcher moduleEventWatcher;
22 |
23 | @Command("addLog")// 模块命令名
24 | public void addLog() {
25 | new EventWatchBuilder(moduleEventWatcher)
26 | .onClass("com.online.test.TestAdd")// 想要对 TestAdd 这个类进行切面
27 | .onBehavior("test")// 想要对上面类的 test 方法进行切面
28 | .onWatch(new AdviceListener() {
29 | //对方法执行之前执行
30 | @Override
31 | protected void before(Advice advice) throws Throwable {
32 | log.info("sandbox切入成功!!!!!!");
33 | //获取方法的所有参数
34 | Object[] parameterArray = advice.getParameterArray();
35 | if (parameterArray != null) {
36 | for (Object po : parameterArray) {
37 | log.info("形参类型为:" + po.getClass().getName() + "!!!!!!!");
38 | log.info("形参值为:" + po + "!!!!!!!");
39 | }
40 | }
41 | }
42 | });
43 | }
44 | }
--------------------------------------------------------------------------------
/springboot-demo/pom.xml:
--------------------------------------------------------------------------------
1 |
2 |
5 |
6 | demo
7 | com.online
8 | 1.0-SNAPSHOT
9 |
10 | 4.0.0
11 |
12 | springboot-demo
13 |
14 |
15 |
16 | org.springframework.boot
17 | spring-boot-starter
18 |
19 |
20 |
21 | org.springframework.boot
22 | spring-boot-starter-logging
23 |
24 |
25 |
26 |
27 | org.springframework.boot
28 | spring-boot-starter-test
29 | test
30 |
31 |
32 |
33 |
34 |
35 |
36 | org.apache.maven.plugins
37 | maven-compiler-plugin
38 |
39 | 1.8
40 | 1.8
41 |
42 |
43 |
44 | org.springframework.boot
45 | spring-boot-maven-plugin
46 |
47 |
48 |
49 | repackage
50 |
51 |
52 |
53 |
54 |
55 |
56 |
--------------------------------------------------------------------------------
/springboot-demo/src/main/java/com/online/MyApp.java:
--------------------------------------------------------------------------------
1 | package com.online;
2 |
3 | import org.springframework.boot.SpringApplication;
4 | import org.springframework.boot.autoconfigure.SpringBootApplication;
5 |
6 | @SpringBootApplication
7 | public class MyApp {
8 | public static void main(String[] args) {
9 | SpringApplication.run(MyApp.class, args);
10 | }
11 | }
12 |
--------------------------------------------------------------------------------
/springboot-demo/src/main/java/com/online/test/TestAdd.java:
--------------------------------------------------------------------------------
1 | package com.online.test;
2 |
3 | import lombok.extern.slf4j.Slf4j;
4 | import org.springframework.boot.ApplicationArguments;
5 | import org.springframework.boot.ApplicationRunner;
6 | import org.springframework.stereotype.Component;
7 |
8 | import java.util.concurrent.atomic.LongAdder;
9 |
10 |
11 | @Slf4j
12 | @Component
13 | public class TestAdd implements ApplicationRunner {
14 |
15 | private final LongAdder longAdder = new LongAdder();
16 |
17 | @Override
18 | public void run(ApplicationArguments args) throws Exception {
19 | while (true) {
20 | longAdder.add(1);
21 | try {
22 | Thread.sleep(2000);
23 | } catch (InterruptedException e) {
24 | e.printStackTrace();
25 | }
26 | test(longAdder);
27 | }
28 | }
29 |
30 | private void test(LongAdder longAdder) {
31 | log.info("Test------->" + longAdder);
32 | }
33 |
34 | }
35 |
--------------------------------------------------------------------------------
/springboot-demo/src/main/resources/application.yml:
--------------------------------------------------------------------------------
1 |
2 | server:
3 | port: 8080
4 |
5 | spring:
6 | profiles:
7 | active: dev
8 |
--------------------------------------------------------------------------------
/springboot-demo/src/main/resources/logback-spring.xml:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 |
5 |
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 | ${PATTERN}
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
27 |
28 | INFO
29 | ACCEPT
30 | DENY
31 |
32 |
33 |
34 | ${TEST_FILE_PATH}/info.%d{yyyy-MM-dd}.log
35 |
36 | 100
37 |
38 |
39 | ${PATTERN}
40 |
41 |
42 |
43 |
44 |
45 | WARN
46 | ACCEPT
47 | DENY
48 |
49 |
50 |
51 | ${TEST_FILE_PATH}/warn.%d{yyyy-MM-dd}.log
52 |
53 | 100
54 |
55 |
56 | ${PATTERN}
57 |
58 |
59 |
60 |
61 |
62 | ERROR
63 |
64 |
65 |
66 |
67 | ${TEST_FILE_PATH}/error.%d{yyyy-MM-dd}.log
68 |
69 | 100
70 |
71 |
72 | ${PATTERN}
73 |
74 |
75 |
76 |
77 |
78 |
79 |
80 |
81 |
82 |
83 |
84 |
85 |
86 | WARN
87 | ACCEPT
88 | DENY
89 |
90 |
91 |
92 | ${PRO_FILE_PATH}/warn.%d{yyyy-MM-dd}.log
93 |
94 | 100
95 |
96 |
97 | ${PATTERN}
98 |
99 |
100 |
101 |
102 |
103 | ERROR
104 |
105 |
106 |
107 |
108 | ${PRO_FILE_PATH}/error.%d{yyyy-MM-dd}.log
109 |
110 | 100
111 |
112 |
113 | ${PATTERN}
114 |
115 |
116 |
117 |
118 |
119 |
120 |
121 |
122 |
--------------------------------------------------------------------------------