java中的动态加载和热替换

58 篇文章 0 订阅
30 篇文章 2 订阅

1.C++编写的程序需要经过编译称为目标文件,然后在程序执行之前进行链接后才可以称为可以运行的可执行程序,这个链接可以发生在程序运行之前,也可以发生在程序运行后(在内核中完成链接过程)再被执行。(运行可以理解为双击打开)。而Java则只需要编译成字节码,然后交给JVM解析器去链接执行就可以了。(C++系列也拥有动态加载和动态链接等概念)


2.Java的动态加载实际上就是程序在执行过程中可以根据程序设定去加载需要被执行的字节码文件。


3.热替换属于动态加载的一种,但是热替换是特殊的动态加载机制。


4.动态加载在Java中有2种实现,第一种通过ClassLoader.loadClass()去加载,ClassLoader最高级别的类加载器,所有的类都归他管理,用loadClass加载的类,是未经过初始化的,所以很多静态变量和方法无法被使用,第二种方法则是,Class.forName().用这个方法加载的类已经经过初始化。


5.而如何实现热替换呢?首先我们要知道ClassLoader中的loadClass在加载类的时候会检测该类是否已经存在,如果存在则不会去加载,如果不存在则加载该类并缓存。所以默认的ClassLoader是无法实现热替换的。换句话说,要实现热替换就必须实现一个自己的MyClassLoader,实现一个自己的用于加载类的方法findClass(),在方法里面要做的事情就是读取本地字节码文件,只用父类的defineClass()方法去解析它。这样就可以获取新的类了,而旧的类由于ClassLoader不可达,所以会被GC回收。


下面是MyClassLoader的代码:

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;

public class MyClassLoader extends ClassLoader {
    public MyClassLoader() {
    }

    public Class<?> findClass(String name) throws ClassNotFoundException {
        String classPath = MyClassLoader.class.getResource("/").getPath();
        String fileName = name.replace(".", "/") + ".class";
        File classFile = new File(classPath, fileName);
        if(!classFile.exists()) {
            throw new ClassNotFoundException(classFile.getPath() + " 不存在");
        } else {
            ByteArrayOutputStream bos = new ByteArrayOutputStream();
            ByteBuffer bf = ByteBuffer.allocate(1024);
            FileInputStream fis = null;
            FileChannel fc = null;

            try {
                fis = new FileInputStream(classFile);
                fc = fis.getChannel();

                while(fc.read(bf) > 0) {
                    bf.flip();
                    bos.write(bf.array(), 0, bf.limit());
                    bf.clear();
                }
            } catch (FileNotFoundException var20) {
                var20.printStackTrace();
            } catch (IOException var21) {
                var21.printStackTrace();
            } finally {
                try {
                    fis.close();
                    fc.close();
                } catch (IOException var19) {
                    var19.printStackTrace();
                }

            }

            return this.defineClass(bos.toByteArray(), 0, bos.toByteArray().length);
        }
    }
}

  • 3
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值