请教:应用服务器如何识别被更新的class文件,是通过ClassLoader吗?

06-07-26 诸葛
    

我拿Tomcat5.0.28做的试验

public class Test{

static int a = 99;

static{

a = 5662;

System.out.println("类初始化");

}

public Test(){

System.out.println("创建了一个TTTTT的实例");

}

public static void stm(){

System.out.println("--------static-------!"+a);

}

public void m(){

System.out.println("--------nonstatic-------!"+a);

}

protected void finalize() throws Throwable {

super.finalize();

System.out.println("--------对象被释放---------!");

}

}

将创建一个Test类的对象,放到session中,

会打印出:

类初始化

创建了一个TTTTT的实例

然后执行m方法,打印出("--------nonstatic-------!5662

然后修改Test类,将m方法改为:

public void m(){

System.out.println("----modified----nonstatic-------!"+a);

}

再次执行,打印出的就就是新的方法中的内容:----modified----nonstatic-------!5662

但是没有打印出“类初始化”,也就是说没有执行static初始块。

同样的试验,发现static的方法也是被更新后的。

同时,我也尝试打印出Test.class.hashcode();,发现这个值一直没有变,这个方法是来自Object,Class类并没有override它,还有一些发现,我总结了一下tomcat的特点:

*Tomcat会识别应用目录下Class文件的更新操作,并通过某种机制将新的字节码替代旧的字节码

*Tomcat不会重新加载一个类,因为static块没有被执行

*Tomcat动态更新不允许增加方法、减少方法、增加/减少字段等操作。这些操作都会引起Tomcat崩溃。

至于Tomcat对servlet的更新相对就简单一些了,毕竟servlet实现了接口,而且都是完全由容器管理的,创建、更新、再次加载在理论上也都不是什么难事。可是对于Test这种完全自定义的类,实现动态更新让我困扰不已。小弟尝试从ClassLoader的角度分析这个问题,但是最后发现那样是没有办法达到这种效果的。小弟也尝试从Class类入手,现在还没有结果,请问哪位大虾能给小弟指点迷津,小弟不胜感激!

    

banq
2006-07-26 18:12

一般监视Web项目的web.xml文件,这是肯定的,其他则看具体容器了。

诸葛
2006-07-26 18:31

现在最让我弄不明白的是Tomcat这种服务器是什么更新的像Test这种自定义类的呢?按照我对ClassLoader的理解,是没办法实现Tomcat已经实现的那些功能的,请教banq。

诸葛
2006-07-26 19:00

现在Tomcat实现的功能如下:

*在class文件被更新的时候,如果被前后两个版本的class文件兼容(没有添加或者删除一个方法或者变量),Tomcat就会将最新的字节码加载,以后执行的都是更新后的字节码。

*不会再次初始化一个类(static块不会被执行)

表现在应用中,就是所有的对象执行的方法都是新的了,包括在更新前创建的对象。对象的hashcode()以及对象的getClass().hashcode()都没有变化。真让人匪夷所思。好像真的是一个类被reload了一样。

ps:因为一般spring都部署在应用服务器下,如Tomcat,所以reload的工作可以交给应用服务器去做。但是spring本身并没有reload类的功能,我研究这个的目的是希望给spring增加这个功能。

诸葛
2006-07-27 09:02

今天又尝试了一下不使用eclipse,而是将编译好的新版本的class文件手动拷贝到tomcat的目录下,结果发现代码也是被更新了的。感觉Tomcat这方面做的真的很不错,真希望在脱离了App Server的Spring也能有这种特性。

2Go 1 2 下一页