利用ClassLoader实现动态热布署

转载 2011年01月11日 18:33:00

          大型应用中,系统是不能轻易停机的,一般选择升级都是选在晚上人少的时候进行停机维护。这样大大的降低了系统的可用性,也提高了系统维护的成本。因此如果能够实现在不停机的情况下能够进行系统的维护或者升级,则能够很好的解决上面的情况。在JAVA中我们可以利用CustomerClassLoader来实现以上机制。

在开始之前先简介一下JAVA中的ClassLoader机制。Java中类的实例化分为两部分:类的加载与类的实例化。而类的加载一般分为两种情况,显式加载和隐式加载。显示加载就是我们使用Class.forName而隐式加载的话就是我们平常使用最多的new.new关键字会在后台为我们做一些工作。

JAVA的类加载机制是分为几个层次来加载的。首先我们来看一下JAVA的加载器的层次结构:

 

ClassLoad Struct

 

 

1,BootStrapClassLoader是根加载器,它默认加载的是jre/lib目录下面的jar.或者是你在jdk的启动参数里面指定的:-XbootClasspath

2,ExtClassLoader加载器,它默认加载的是jre/lib/ext目录下面的jar,或者是启动参数里-Djava.ext.dirs 指定的目录

3,AppClassLoader加载器,它默认加载的是classpath变量指定的目录,其实就是我们应用程序的class目录。

4,CustomeClassLoader加载器,这是我们自已定义的加载器,必须要继承ClassLoader类。可以根据用户的需要定制自己的类加载过程,在运行期进行指定类的动态实时加载

而JDK的加载过程分为两个过程,第一步是:从下到上检查加载器的命名空间内(每个class在命名空间内只存在有一份)是否已有要加载的Class.如果找到则直接返回其引用,如果没有。则从上到下从各自的目录下去加载指定的class.如果到了最底层还没有加载成功。则抛出noclassfound的异常。其加载流程,详见如下图:

 

 

 

 

接下来,我们初步的了解了JDK的ClassLoader加载机制后,可见我们要实现动态的热布署,我们可以用CustomerClassLoader来实现我们的功能。自定义的ClassLoader需求要继承ClassLoader类。下面对于ClassLoader中的几个重要方法做一下介绍。

findLoadedClass:从当前类加载器的命名空间内查找指定的class,如果存在则返回其引用。不存在则返回null

getSystemClassLoader:调用系统使用的加载器,有时候我们自定义的类加载器可以调用它来执行一些其它的事情

resolveClass:链接一个指定的类,在某些情况下保证这个类一定可以用

defineClass:从class字节文件生成一个class对象

loadClass:加载类的入口方法,显式的加载类的方法。

下面我们看一下实现的自定义的类加载器:

 

 

 

 

在以上代码段中,我们在构造方法中,调用了super(null),这样的做法就是让我们定制的加载器的父加载器为null.这样避免我们定义的类被父加载器(AppClassLoader)抢先加载。在loadClass中我们首先从自已的类加载器的命名空间内查找要加载的类。如果没有找到。则让系统的加载器加载。

 

 

 

调用的类:

 

 

 

在以上类中,我们让系统每隔三秒种调用一次run程序。然后运行我们系统,可以看到控制台打出如下语句:
hello version 1
hello version 1

热下来我们不要停我们的应用,直接修改Foo的代码如下:

可见修改后打出如下语句:

hello version 1
hello version 1
hello version 1
hello version 2
hello version 2

代表已经替换成功了。

注意:有朋友会说为什么不把上面的反射的代码改成

 

 

 

 

这样呢,这样更明了,但是这种情况下。系统会报错:ClassCastException,因为你强转的时候的Foo是由AppClassLoader加载的,而我们的foo是由自定义的加载器加载的。在JDK中,继使两个类的类型相同,但是由不同的加载器加载的话。虚拟机也会认为这是不同的类型。但是我们可以通过接口来实现。是不会报错的,可以改成如下代码,则可以运行通过:

 

以上代码中Ifoo是Foo接口。
当然,要实现一个在线自动升级热布署的系统光靠上面这一点代码是不够的,还需要有完善的回退机制,检查机制等。但是以上部分做为core部分,基于以上部分是完全可以打造一个不停机升级的热布署应用。解决大型应用中的维护和升级的问题。

 

 

使用自己的ClassLoader实现热替换

首先实现一个自己的ClassLoader
  • is_zhoufeng
  • is_zhoufeng
  • 2014年05月22日 17:00
  • 9596

Java Class的热替换 自定义ClassLoader加载.class(java热部署实现 )

本文是java热替换的实验,参考了 Java 类的热替换 —— 概念、设计与实现http://www.ibm.com/developerworks/cn/java/j-lo-hotswapcls...
  • wangxin1982314
  • wangxin1982314
  • 2017年03月23日 14:27
  • 1130

慕课网Spring Boot热部署第一讲:java类热加载案例

1、热部署使用场景          本地调试     线上发布          全年不间断运行,重发布程序后不重启项目          本地线上都适用     无需重启服务器 ...
  • qq_20367813
  • qq_20367813
  • 2018年01月24日 11:52
  • 16

java利用classloader实现热部署

热部署,即需要jvm释放之前加载的业务class,且重新加载最新的业务class,并释放之前的class(卸载),其实类和普通对象一样都是对象,即如果从gc root除非,没有引用此类的别的对象存在,...
  • chaofanwei2
  • chaofanwei2
  • 2016年05月02日 22:34
  • 4874

Java Class的热替换 自定义ClassLoader加载.class

本文是java热替换的实验,参考了 Java 类的热替换 —— 概念、设计与实现http://www.ibm.com/developerworks/cn/java/j-lo-hotswapcls...
  • z69183787
  • z69183787
  • 2014年06月07日 21:08
  • 5532

自定义classloader实现JAVA热替换

这几天学习了下JVM的原理,在看一个视频教程,上面上一个这样的题目: 1. 实现热替换。    运行一个程序HelloMain,他会循环调用另外一个类Worker.doit()方法。此时,对Wor...
  • puhaiyang
  • puhaiyang
  • 2017年10月06日 15:37
  • 388

NetBeans Web应用热部署

将.war文件拷贝至C:/Documents and Settings/yourname/.netbeans/6.5/apache-tomcat-6.0.18_base/webapps文件夹中,然后在...
  • tanghw
  • tanghw
  • 2009年02月13日 14:04
  • 1951

jrebel实现Java热布署

一 、下载JRebel6.4.8的破解文件 首先从网上下载: JRebel 6.4.8 update-site.zip jrebel_6.4.8_agent_crack.zi...
  • qq_35893120
  • qq_35893120
  • 2017年11月24日 16:48
  • 106

java中插件机制和热升级的实现方案

引言插件式的架构可以为系统带来极高的扩展性。典型的一个例子就是eclipse。我们可以下载各种各样的插件来不断丰富eclipse的功能,而eclipse本身却不需要作任何改动。那么在java中如何实现...
  • Axceluxy
  • Axceluxy
  • 2015年04月01日 01:14
  • 3954

Java中的ClassLoader 动态加载机制

前言: Android中的动态加载机制能更好的优化我们的应用,同时实现动态的更新,这就便于我们管理我们的应用,通过插件化来减轻我们的内存以及CPU消耗,在不发布新版本的情况下能更新某些模块。 当然...
  • qq_27540131
  • qq_27540131
  • 2016年07月03日 23:09
  • 4516
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:利用ClassLoader实现动态热布署
举报原因:
原因补充:

(最多只允许输入30个字)