背景
- 项目源代码
public class HotDeployDemo {
public static void main(String[] arrstring) throws InterruptedException {
for (int i = 0; i >= 0; ++i) {
new Thread(new Runnable(){
@Override
public void run() {
for (int i = 0; i >= 0; ++i) {
try {
Thread.sleep(5000L);
System.out.println("线程名: " + Thread.currentThread().getName() + ", j: " + i);
continue;
}
catch (InterruptedException interruptedException) {
interruptedException.printStackTrace();
}
}
}
}, "Thread_" + i).start();
Thread.sleep(30000L);
}
}
}
- 执行结果
热部署
- Arthas环境初始化
https://arthas.aliyun.com/doc/download.html
// 启动方式
java -jar arthas-boot.jar
-
选择对应的项目序号
-
使用jad命令反编译得到新的源文件
jad --source-only HotDeployDemo > ./2/HotDeployDemo.java
- 修改新的源文件
public class HotDeployDemo {
public static void main(String[] arrstring) throws InterruptedException {
for (int i = 0; i >= 0; ++i) {
new Thread(new Runnable(){
@Override
public void run() {
for (int i = 0; i >= 0; ++i) {
try {
Thread.sleep(5000L);
// 将打印的变量i变为j,当新的线程执行时显示的变量就会变为j
System.out.println("线程名: " + Thread.currentThread().getName() + ", j: " + i);
continue;
}
catch (InterruptedException interruptedException) {
interruptedException.printStackTrace();
}
}
}
}, "Thread_" + i).start();
Thread.sleep(30000L);
}
}
}
- 获得原来的类加载器
sc -d HotDeployDemo
- 编译新的源文件
// -d参数表示制定目标字节码文件的位置
mc -classLoaderClass sun.misc.Launcher$AppClassLoader ./2/HotDeployDemo.java -d ./2/
- 将原来的字节码文件替换成新的字节码文件
redefine 2/HotDeployDemo$1.class
- 执行结果