热替换实战

一 代码结构图

二 代码

1 被动态替换的类

package chapter04.java1;

/**
* replaced class
*/
public class Demo1 {
    public void hot() {
        // System.out.println("OldDemo1"); // A:old class print
        // System.out.println("NewDemo1"); // B:new class print
    }
}

2 自定义类加载器

package chapter04.java1;

import java.io.*;
import java.nio.ByteBuffer;
import java.nio.channels.Channels;
import java.nio.channels.FileChannel;
import java.nio.channels.WritableByteChannel;

/**
* 自定义类的加载器
*/
public class MyClassLoader extends ClassLoader {
    private String rootDir;

    public MyClassLoader(String rootDir) {
        this.rootDir = rootDir;
    }

    protected Class<?> findClass(String className) throws ClassNotFoundException {
        Class clazz = this.findLoadedClass(className);
        FileChannel fileChannel = null;
        WritableByteChannel outChannel = null;
        if (null == clazz) {
            try {
                String classFile = getClassFile(className);
                FileInputStream fis = new FileInputStream(classFile);
                fileChannel = fis.getChannel();
                ByteArrayOutputStream baos = new ByteArrayOutputStream();
                outChannel = Channels.newChannel(baos);
                ByteBuffer buffer = ByteBuffer.allocateDirect(1024);
                while (true) {
                    int i = fileChannel.read(buffer);
                    if (i == 0 || i == -1) {
                        break;
                    }
                    buffer.flip();
                    outChannel.write(buffer);
                    buffer.clear();
                }

                byte[] bytes = baos.toByteArray();
                clazz = defineClass(className, bytes, 0, bytes.length);
            } catch (FileNotFoundException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            } finally {
                try {
                    if (fileChannel != null)
                        fileChannel.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
                try {
                    if (outChannel != null)
                        outChannel.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        return clazz;
    }

    /**
     * 类文件的完全路径
     */
    private String getClassFile(String className) {
        return rootDir + "/" + className.replace('.', '/') + ".class";
    }
}

3 测试类

package chapter04.java1;

import java.lang.reflect.Method;

public class LoopRun {
    public static void main(String args[]) {
        while (true) {
            try {
                // 1. 创建自定义类加载器的实例
                String rootDir = "E:\\jvmp2\\";
                MyClassLoader loader = new MyClassLoader(rootDir);
                // 2. 加载指定的类
                Class clazz = loader.findClass("chapter04.java1.Demo1");
                // 3. 创建运行时类的实例
                Object demo = clazz.newInstance();
                // 4. 获取运行时类中指定的方法
                Method m = clazz.getMethod("hot");
                // 5. 调用指定的方法
                m.invoke(demo);
                Thread.sleep(5000);
            } catch (Exception e) {
                System.out.println("not find");
                try {
                    Thread.sleep(5000);
                } catch (InterruptedException ex) {
                    ex.printStackTrace();
                }
            }
        }
    }
}

三 测试

1 仅让 Demo1 的 B 处代码生效,编译 Demo1.java

E:\jvmp2\chapter04\java1>javac Demo1.java

2 运行 main,此时控制台打印如下 

NewDemo1

NewDemo1

NewDemo1

NewDemo1

3 过上一段时间,仅让 Demo1 的 A 处代码生效,编译 Demo1.java,此时控制台打印如下

NewDemo1

NewDemo1

NewDemo1

NewDemo1

OldDemo1

OldDemo1

OldDemo1

OldDemo1

4 打印发生了变化,说明热替换生效。

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值