利用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部分,基于以上部分是完全可以打造一个不停机升级的热布署应用。解决大型应用中的维护和升级的问题。

 

 

Project Class Loader

应用场景:在eclipse插件开发中,插件中的某个动作需要使用当前java工程的classpath。例如在插件需要访问的XML资源文件可能已经打包在某个jar文件中了,而jar文件正好设置在当前工程的...
  • Dato
  • Dato
  • 2007年12月10日 16:39
  • 1924

ClassLoader与System学习笔记

* 类加载器负载加载类对象、资源 * 一般策略是将给定名称转为文件名,然后从文件系统中进行加载 * 类加载器采用委托机制进行加载类和资源-->在加载类或者资源之前将操作委托给父加载器进行加载 *...

JRebel安装使用说明(真正的实现热布署)

开发环境下,tomcat对热布署的支持还是比较弱,致使开发过程中浪费大量时间在重起服务上。发现了Jrebel,它对热布署的支持相对比较全面。 虽然Jrebel官方号称使用它不存在内存泄漏问题,但...

jrebel实现Java热布署

一 、下载JRebel6.4.8的破解文件 首先从网上下载: JRebel 6.4.8 update-site.zip jrebel_6.4.8_agent_crack.zi...

java代码实现利用 classloader 动态加载 jar包、文件夹到classpath中

转载自BlogJava。http://www.blogjava.net/jnbzwm/archive/2011/04/01/347491.html 在项目中实现了一个工具(独立运行的Ja...
  • fireson
  • fireson
  • 2011年09月09日 11:22
  • 1259

利用Cobbler批量布署CentOS

从事网游运维的兄弟们应该深有感触,往往在开新服的时候需要大批量的布署新的服务器,时间紧迫而且量大,装系统、初始化,枯燥而又乏味,有时还容易出错, 为了解放我们的双手,所以要实现自动化,Red Hat ...

搭建git服务器及利用git hook自动布署代码

我喜欢 github,我现在的个人代码全部是托管在上面了,但是一些公司或者某些项目不适合放入github中,你希望能有一个完全私有的仓库,如果你有一台服务器,这显然是很容易办到的事。 下面简单的...
  • jackiej
  • jackiej
  • 2012年05月25日 12:37
  • 14162

利用classloader动态加载jar包

利用classloader动态加载jar包
  • zsllxbb
  • zsllxbb
  • 2015年11月18日 09:47
  • 1670

利用自定义ClassLoader和接口逻辑后台可刷新缓存实现java-web项目的动态发布

1。设计思路 通过后台管理界面上传jar包实现动态发布

实现java classloader 动态加载jar包

业务描述 : 有两个jar包mylib.jar,mylib2.jar , 其中mylib.jar依赖mylib2.jar     我在eclipse的classpath上不加载这两个jar包     ...
  • AS_JOPO
  • AS_JOPO
  • 2015年12月29日 12:31
  • 416
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:利用ClassLoader实现动态热布署
举报原因:
原因补充:

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