java热部署

java热部署

问题:jvm运行过程中怎么加载生成的java类

  • 生成类
  • 编译类
  • 加载类
  • 反射执行类
public class CompilerMain {
    public static void main(String[] args) throws Exception {
        testCompiler();
    }
    public static void testCompiler() throws Exception {
        String currentDir = System.getProperty("user.dir");
        // 將源码写入文件中
        String src = "public class TestCompiler {"
                + "    public void disply() {"
                + "    System.out.println(\"Hello\");"
                + "}}";
        String filename = currentDir + "/src/TestCompiler.java";
        File file = new File(filename);
        FileWriter fw = new FileWriter(file);
        fw.write(src);
        fw.flush();
        fw.close();

        // 使用JavaCompiler 编译java文件
        JavaCompiler jc = ToolProvider.getSystemJavaCompiler();
        StandardJavaFileManager fileManager = jc.getStandardFileManager(null, null, null);
        Iterable<? extends JavaFileObject> fileObjects = fileManager.getJavaFileObjects(filename);
        CompilationTask cTask = jc.getTask(null, fileManager, null, null, null, fileObjects);
        cTask.call();
        fileManager.close();
        // 使用URLClassLoader加载class到内存
        URL[] urls = new URL[] { new URL("file:/" + currentDir + "/src/") };
        URLClassLoader cLoader = new URLClassLoader(urls);
        Class<?> c = cLoader.loadClass("TestCompiler");
        cLoader.close();
        // 利用class创建实例,反射执行方法
        Object obj = c.newInstance();
        Method method = c.getMethod("disply");
        method.invoke(obj);
    }
}

问题:jvm在运行过程中怎么重写加载一个已经进入内存的类?

package 自定义类加载器;

import javax.tools.JavaCompiler;
import javax.tools.JavaFileObject;
import javax.tools.StandardJavaFileManager;
import javax.tools.ToolProvider;
import java.io.*;
import java.lang.reflect.Method;

/**
 * @作者 mayn
 * @创建时间 2020/6/6
 * @项目名称 ClassLoders
 * @包名 自定义类加载器
 * @描述
 */

public class MyClassLoader extends ClassLoader{
    private String directory;//加载类所在的目录

    //默认父类加载器就是系统加载器
    public MyClassLoader(String directory){
        this.directory=directory;
    }

    public MyClassLoader(String directory,ClassLoader parent){
        super(parent);
        this.directory=directory;

    }

    @Override
    protected Class<?> findClass(String name) throws ClassNotFoundException {
        //将类名转化为目录
        String file=directory+ File.separator+name.replace(".",File.separator)+".class";

        try {
            //构建输入流
            InputStream fileInputStream = new FileInputStream(file);
            //构建字节输出流
            ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
            byte []buf=new byte[1024];
            int len=-1;
            while ((len=fileInputStream.read(buf))!=-1){
                byteArrayOutputStream.write(buf,0,len);
            }
            //读取到的二进制数据
            byte []data=byteArrayOutputStream.toByteArray();
            fileInputStream.close();
            byteArrayOutputStream.close();
            return defineClass(name,data,0,data.length);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

    public static void main(String[] args) throws ClassNotFoundException, IllegalAccessException, InstantiationException, IOException {

        MyClassLoader myClassLoader = new MyClassLoader("D:\\Idea\\data\\ClassLoders\\out\\production\\ClassLoders");

        Class<?> aClass = myClassLoader.findClass("自定义类加载器.Test2");
        aClass.newInstance();

        //重写Test2这个类
        FileWriter fileWriter = new FileWriter("./src/自定义类加载器/Test2.java");
        fileWriter.write("package 自定义类加载器;\n" +
                "public class Test2 {\n" +
                "    public Test2() {\n" +
                "        System.out.println(\"2\");\n" +
                "    }\n" +
                "}");
        fileWriter.close();

        //重写编译Test2这个类
        String filename="./src/自定义类加载器/Test2.java";
        JavaCompiler jc = ToolProvider.getSystemJavaCompiler();
        StandardJavaFileManager fileManager = jc.getStandardFileManager(null, null, null);
        Iterable<? extends JavaFileObject> fileObjects = fileManager.getJavaFileObjects(filename);
        JavaCompiler.CompilationTask cTask = jc.getTask(null, fileManager, null, null, null, fileObjects);
        cTask.call();
        fileManager.close();

        //重写加载这个类,需要重写findClass方法,否则,双亲委派机制,加载的字节码文件,依然是修改前的类的字节码
        MyClassLoader myClassLoader1 = new MyClassLoader("D:\\Idea\\data\\ClassLoders\\src",myClassLoader);
        Class<?> aClass1 = myClassLoader1.findClass("自定义类加载器.Test2");
        aClass1.newInstance();



    }
}

这是加载前Test2类

package 自定义类加载器;
public class Test2 {
    public Test2() {
        System.out.println("3");
    }
}

这是修改后,并且进入内存的Test2类

package 自定义类加载器;
public class Test2 {
    public Test2() {
        System.out.println("2");
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值