• JAVA热部署原理


    1、热部署是什么?

    对于Java应用程序来说,热部署就是在运行时更新Java类文件。
    2、热部署有什么用?
    可以不重启应用的情况下,更新应用。举个例子,就像电脑可以在不重启的情况下,更换U盘。
    OSGI也正是因为它的模块化和热部署,才显得热门。
    3、热部署的原理是什么?
    想要知道热部署的原理,必须要了解java类的加载过程。一个java类文件到虚拟机里的对象,要经过如下过程。
    首先通过java编译器,将java文件编译成class字节码,类加载器读取class字节码,再将类转化为实例,对实例newInstance就可以生成对象。
    类加载器ClassLoader功能,也就是将class字节码转换到类的实例。
    在java应用中,所有的实例都是由类加载器,加载而来。
    一般在系统中,类的加载都是由系统自带的类加载器完成,而且对于同一个全限定名的java类(如com.csiar.soc.HelloWorld),只能被加载一次,而且无法被卸载。
    这个时候问题就来了,如果我们希望将java类卸载,并且替换更新版本的java类,该怎么做呢?
         既然在类加载器中,java类只能被加载一次,并且无法卸载。那是不是可以直接把类加载器给换了?答案是可以的,我们可以自定义类加载器,并重写ClassLoader的findClass方法。想要实现热部署可以分以下三个步骤:
    1、销毁该自定义ClassLoader
    2、更新class类文件
    3、创建新的ClassLoader去加载更新后的class类文件。
    示例代码如下:
     1 package com.csair.soc.hotswap;
     2 
     3 import java.io.IOException;
     4 import java.io.InputStream;
     5 /**
     6  * 自定义类加载器,并override findClass方法
     7  */
     8 public class MyClassLoader extends ClassLoader{
     9      @Override
    10      public Class<?> findClass(String name) throws ClassNotFoundException{
    11             try{
    12                 String fileName = name.substring(name.lastIndexOf("." )+1) + ".class" ;
    13                 InputStream is = this.getClass().getResourceAsStream(fileName);
    14                  byte[] b = new byte[is.available()];
    15                 is.read(b);
    16                  return defineClass(name, b, 0, b. length);
    17            } catch(IOException e){
    18                  throw new ClassNotFoundException(name);
    19            }
    20      }
    21 }
    需要更新的类文件:
    1 package com.csair.soc.hotswap;
    2 public class HelloWorld {
    3      public void say(){
    4            System. out.println( "Hello World V1");
    5      }
    6 }
    在工程的根目录下,生成V2版本的HelloWorld.class,内容如下。
    1 package com.csair.soc.hotswap;
    2 public class HelloWorld {
    3       public void say(){
    4            System. out.println( "Hello World V2");
    5      }
    6 }
    测试主程序
     1 package com.csair.soc.hotswap;
     2 
     3 import java.io.File;
     4 import java.lang.reflect.Method;
     5 
     6 public class Hotswap {
     7      public static void main(String[] args) throws Exception {
     8             loadHelloWorld();
     9             // 回收资源,释放HelloWorld.class文件,使之可以被替换
    10            System. gc();
    11            Thread. sleep(1000);// 等待资源被回收
    12            File fileV2 = new File( "HelloWorld.class");
    13            File fileV1 = new File(
    14                       "bin\com\csair\soc\hotswap\HelloWorld.class" );
    15            fileV1.delete(); //删除V1版本
    16            fileV2.renameTo(fileV1); //更新V2版本
    17            System. out.println( "Update success!");
    18             loadHelloWorld();
    19      }
    20 
    21      public static void loadHelloWorld() throws Exception {
    22            MyClassLoader myLoader = new MyClassLoader(); //自定义类加载器
    23            Class<?> class1 = myLoader
    24                      .findClass( "com.csair.soc.hotswap.HelloWorld");//类实例
    25            Object obj1 = class1.newInstance(); //生成新的对象
    26            Method method = class1.getMethod( "say");
    27            method.invoke(obj1); //执行方法say
    28            System. out.println(obj1.getClass()); //对象
    29            System. out.println(obj1.getClass().getClassLoader()); //对象的类加载器
    30      }
    31 }
    输出结果:
    Hello World V1
    class com.csair.soc.hotswap.HelloWorld
    com.csair.soc.hotswap.MyClassLoader@bfc8e0
    Update success!
    Hello World V2
    class com.csair.soc.hotswap.HelloWorld
    com.csair.soc.hotswap.MyClassLoader@860d49
    根据结果可以看到,在没有重启应用的情况下,成功的更新了HelloWorld类。
    以上只是热部署的最简单的原理实践,实际情况会复杂的多。OSGI的最关键理念就是应用模块(bundle)化,对于每一个bundle,都有其自己的类加载器,当需要更新bundle时,把bundle和它的类加载器一起替换掉,就可以实现模块的热替换。


    参考资料

    深入理解java虚拟机
    深入探讨 Java 类加载器 http://www.ibm.com/developerworks/cn/java/j-lo-classloader/
     
  • 相关阅读:
    移动端 细节点
    基于新版 node 的 vue 脚手架搭建
    全屏展示
    Vue 小实例
    移动端 模拟键盘 盖住表单
    decodeURI decodeURIComponent
    简单时钟
    全选 反选 传统写法
    星级点评 面向过程的传统写法
    JQ字符串截取
  • 原文地址:https://www.cnblogs.com/pfxiong/p/4070462.html
Copyright © 2020-2023  润新知