比较详细的java热更新agentmain的使用

最近在研究java的热更新,花了些时间精力在网上找了些资料,发现好多资料讲的不清不楚(可能是自己技术菜看不懂),没有一篇讲的比较详细的博客,有的还缺省了一些步骤,这还不要紧,要命的是按照他的步骤做了最后没成功还费了半天的无用功你说气不气人。所以今天写下自己在弄的时候遇到的一些坑顺便给填了。

首先单独开一个工程,里边就写一个包含agentmain方法的类比如我的JavaAgent

下面是这个工程得到截图

之后再mavenpom文件中设置MANIFEST.MFAgent-Class值,这个值就是指向上边创建的JavaAgent类路劲

 

<build>
    <finalName>xxx</finalName>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-jar-plugin</artifactId>
            <version>2.3.1</version>
            <configuration>
                <archive>
                    <manifest>
                        <addClasspath>true</addClasspath>
                    </manifest>
                    <manifestEntries>
                        <Agent-Class>
                            org.yztun.JavaAgent
                        </Agent-Class>
                        <Can-Redefine-Classes>true</Can-Redefine-Classes>
                        <Can-Retransform-Classes>true</Can-Retransform-Classes>
                    </manifestEntries>
                </archive>
            </configuration>
        </plugin>
    </plugins>
</build>

上截图

这个只要在pom文件中指定就行,maven打包的时候自己会生成MANIFEST.MF文件并自己设置Agent-Class的值,比如我打包之后的xxx.jar结构是这样的

那么这个工程一打包就完事了

再梳理下上面的步骤

1)创建一个maven工程就命名为yztun吧

2)在yztun工程中创建一个带有agentmain方法的类比如我的JavaAgent类。

3)在pom文件中设置MANIFEST.MF的Agent-Class的值比如我这里JavaAgentorg.yztun.JavaAgent

4)打包,这个不用说了吧,找到maven的install双击等待运行完成就行

接下啦再创建一个启动工程

public class A66 {
    public static void main(String[] args) throws Exception {
        List<VirtualMachineDescriptor> list = VirtualMachine.list();
        for (VirtualMachineDescriptor vmd : list) {
            if (vmd.displayName().endsWith("Main")) {
                VirtualMachine virtualMachine = VirtualMachine.attach(vmd.id());
                virtualMachine.loadAgent("D:/JavaWork/hot-fix/xxx/target/xxx.jar ", "cxs");
                System.out.println("ok");
                virtualMachine.detach();
            }
        }
    }

}

这里的virtualMachine.loadAgent("D:/JavaWork/hot-fix/xxx/target/xxx.jar ", "cxs");其中"D:/JavaWork/hot-fix/xxx/target/xxx.jar "是yztun工程打包之后的群路径那个jar包名是xxx.jar。if (vmd.displayName().endsWith("Main"))就是查找你要热更新那个工程的住函数类名了。等会会讲到,

上截图

这段代码跟第一个工程的代码一样重要,这里是告诉虚拟机你要热更新的那个工程的主入口,等会我们断点看看这个list会有什么东西而VirtualMachineDescriptor这个类需要你引入你安装jdk下的tools包否则找不到这个类

这个自己到自己电脑的jdk安装目录去找然后导入就行,至于路劲这个看你把jdk安装到哪个路径咯。

,好了。到这里其实热更新用到代码都写完了,很少。接下来就说说怎么用吧。

我这里是又创建了一个工程来测试的,其执行代码的主类,就相当于要热更新的工程

Test测试类

接下来运行测试工程,有于测试工程有个死循环所以没隔一秒会调用一次Test.test();

这样当我们的Test.test();内容有变动是就会热更新成功

没热更之前的输出

接下来我们直接在不停止测试工程的情况下修改Test.test();然后编译生成新的class文件然后运行A66的main方法就可热更新成功

再来看输出

  • 7
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
Java Agent是一种Java技术,它可以在程序运行时动态地修改或增强现有的Java类。Java Agent可以用于很多场景,其中之一就是实现Java应用程序的热更新。下面是一个简单的Java Agent热更新的示例: 1.编写Java Agent程序,实现热更新功能。具体实现可以使用Java工具包tools.jar提供的agentmain方法,该方法可以在程序运行时动态地修改或增强现有的Java类。以下是一个简单的Java Agent程序示例: ```java public class HotUpdateAgent { public static void agentmain(String agentArgs, Instrumentation inst) throws Exception { // 获取要更新的类的类名 String className = "com.example.demo.HelloWorld"; // 获取要更新的类的字节码文件 byte[] classBytes = getClassBytes(className); // 重新定义要更新的类 ClassDefinition classDefinition = new ClassDefinition(Class.forName(className), classBytes); inst.redefineClasses(classDefinition); } private static byte[] getClassBytes(String className) throws Exception { // 读取要更新的类的字节码文件 FileInputStream fis = new FileInputStream(className.replaceAll("\\.", "/") + ".class"); ByteArrayOutputStream bos = new ByteArrayOutputStream(); byte[] buffer = new byte[1024]; int len; while ((len = fis.read(buffer)) != -1) { bos.write(buffer, 0, len); } fis.close(); bos.close(); return bos.toByteArray(); } } ``` 2.在需要热更新Java应用程序中,使用Java Agent实现热更新。具体实现可以使用Java命令的-javaagent参数来指定Java Agent程序,并使用HotUpdateServer类来启动Java应用程序。以下是一个简单的Java应用程序示例: ```java public class HelloWorld { public static void main(String[] args) throws Exception { while (true) { System.out.println("Hello World!"); Thread.sleep(1000); } } } ``` 3.使用HotUpdateServer类来启动Java应用程序,并使用Java命令的-javaagent参数来指定Java Agent程序。以下是一个简单的HotUpdateServer类示例: ```java public class HotUpdateServer { public static void main(String[] args) throws Exception { // 获取要更新的Java应用程序的pid String pid = args[0]; // 获取要更新的类的项目目录和类名 String classPath = args[1]; // 获取执行引擎jar的路径 String enginePath = args[2]; // 启动Java应用程序 Process process = Runtime.getRuntime().exec("java -javaagent:" + enginePath + " -cp " + classPath + " HelloWorld"); // 获取Java应用程序的输入流和输出流 InputStream inputStream = process.getInputStream(); OutputStream outputStream = process.getOutputStream(); // 启动热更新线程 new Thread(() -> { while (true) { try { // 等待用户输入命令 Scanner scanner = new Scanner(System.in); String command = scanner.nextLine(); // 发送命令到Java应用程序 outputStream.write((command + "\n").getBytes()); outputStream.flush(); // 读取Java应用程序的输出 byte[] buffer = new byte[1024]; int len; while ((len = inputStream.read(buffer)) != -1) { System.out.write(buffer, 0, len); } } catch (Exception e) { e.printStackTrace(); } } }).start(); // 等待Java应用程序退出 process.waitFor(); } } ```
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值