1.1 下载解压
# 下载最新版本的JVM-SANDBOX
wget http://ompc.oss-cn-hangzhou.aliyuncs.com/jvm-sandbox/release/sandbox-stable-bin.zip
# 解压
unzip sandbox-stable-bin.zip
1.2 挂载目标应用
# 进入沙箱执行脚本
cd sandbox/bin
# 常用命令!!!
# 目标JVM进程73366(假设,使用jps命令查看)
./sandbox.sh -p 73366
#卸载沙箱
./sandbox.sh -p 73366 -S
#查询沙箱
./sandbox.sh -p 73366 -l
#刷新沙箱
./sandbox.sh -p 73366 -F
#使用自定义module执行(my-sandbox-module:自定义的module名字,addLog自定义切入方法名字)
./sandbox.sh -p 73366 -d 'my-sandbox-module/addLog'
#日志配置及查看
#配置文件在 /sandbox/cfg/sandbox-logback.xml
#默认日志路径 ~/logs/sandbox/sandbox.log
本例采用maven多工程模式:(注意自己的父子结构引用)
主pom.xml(参考)
<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.6.RELEASE</version>
<relativePath/> <!-- lookup parent from repository -->
</parent>
<dependencies>
<!--springboot start-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter</artifactId>
<!-- 去除对默认日志的依赖 -->
<exclusions>
<exclusion>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-logging</artifactId>
</exclusion>
</exclusions>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-test</artifactId>
<scope>test</scope>
</dependency>
<!--lombok-->
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<optional>true</optional>
</dependency>
<!--junit-->
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<scope>test</scope>
</dependency>
<!--log start-->
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-api</artifactId>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-core</artifactId>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
</dependency>
<!--springAop-->
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-aop</artifactId>
</dependency>
<!--log end-->
<!--springboot end-->
</dependencies>
springboot-sandbox工程pom.xml
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<executions>
<execution>
<goals>
<goal>repackage</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
module-sandbox工程pom.xml
<dependencies>
<dependency>
<groupId>com.alibaba.jvm.sandbox</groupId>
<artifactId>sandbox-api</artifactId>
<version>1.2.0</version>
</dependency>
<dependency>
<groupId>org.kohsuke.metainf-services</groupId>
<artifactId>metainf-services</artifactId>
<version>1.7</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<configuration>
<archive>
<manifest>
<!-- <mainClass>com.sandbox.test.MySandBoxModule</mainClass>-->
</manifest>
</archive>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
<executions>
<execution>
<id>make-assembly</id> <!-- 此处指定继承合并 -->
<phase>package</phase> <!-- 绑定到打包阶段 -->
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
启动类SandboxApp
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
@SpringBootApplication
public class SandboxApp {
public static void main(String[] args) {
SpringApplication.run(SandboxApp.class, args);
}
}
需要被挂载切入方法的类TestSandbox
import lombok.extern.slf4j.Slf4j;
import org.springframework.boot.ApplicationArguments;
import org.springframework.boot.ApplicationRunner;
import org.springframework.stereotype.Component;
import java.util.concurrent.atomic.LongAdder;
@Slf4j
@Component
public class TestSandbox implements ApplicationRunner {
private final LongAdder longAdder = new LongAdder();
@Override
public void run(ApplicationArguments args) throws Exception {
while (true) {
longAdder.add(1);
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
test(longAdder);
}
}
private void test(LongAdder longAdder) {
log.info("TestSandBox------->" + longAdder);
}
}
打包上传服务器使用java -jar 启动
切入方法类MySandBoxModule
import com.alibaba.jvm.sandbox.api.Information;
import com.alibaba.jvm.sandbox.api.Module;
import com.alibaba.jvm.sandbox.api.annotation.Command;
import com.alibaba.jvm.sandbox.api.listener.ext.Advice;
import com.alibaba.jvm.sandbox.api.listener.ext.AdviceListener;
import com.alibaba.jvm.sandbox.api.listener.ext.EventWatchBuilder;
import com.alibaba.jvm.sandbox.api.resource.ModuleEventWatcher;
import lombok.extern.slf4j.Slf4j;
import org.kohsuke.MetaInfServices;
import javax.annotation.Resource;
@MetaInfServices(Module.class)
@Information(id = "my-sandbox-module")// 模块名,在指定挂载进程后通过-d指定模块,配合@Command注解来唯一确定方法
@Slf4j
public class MySandBoxModule implements Module {
@Resource
private ModuleEventWatcher moduleEventWatcher;
@Command("addLog")// 模块命令名
public void addLog() {
new EventWatchBuilder(moduleEventWatcher)
.onClass("com.sandbox.test.TestSandbox")// 想要对 TestSandbox 这个类进行切面
.onBehavior("test")// 想要对上面类的 bathSave 方法进行切面
.onWatch(new AdviceListener() {
//对方法执行之前执行
@Override
protected void before(Advice advice) throws Throwable {
log.info("sandbox切入成功!!!!!!");
//获取方法的所有参数
Object[] parameterArray = advice.getParameterArray();
if (parameterArray != null) {
for (Object po : parameterArray) {
log.info("形参类型为:" + po.getClass().getName() + "!!!!!!!");
log.info("形参值为:" + po + "!!!!!!!");
}
}
}
});
}
}
使用 mvn clean compile assembly:single打包,上传至sandbox/sandbox-module目录下
参考: https://github.com/alibaba/jvm-sandbox
参考项目: https://github.com/70416450/jvm-sandbox
原文:https://www.cnblogs.com/ttzzyy/p/11414051.html