论坛首页 Java企业应用论坛

HttpSession/App中放的对象, 如果其类代码被容器Reload会怎么样?

浏览 4087 次
精华帖 (0) :: 良好帖 (0) :: 新手帖 (0) :: 隐藏帖 (0)
作者 正文
   发表时间:2006-10-31  
现在大部分的Servlet容器都支持JSP和Servlet的动态重新加载, 也就是源码在运行期间被改过以后会重新编译, 然后废弃原来加载对应类的ClassLoader, 构造新的ClassLoader去加载修改过的bytecode.

突然想到一个问题, 如果被废弃的类曾经构造了对象并且放到 session或者application里去, 那么即使加载它的ClassLoader已经被垃圾回收, 它因为还被appserver通过session或者application在引用, 所以它自己和它的类都没法被垃圾回收.

这还不是最坏的影响, 顶多泄露点内存. 但是如果这样重新加载过以后, 新的代码又需要从session/application取出这个对象来用, 那么其实取出来的修改以前的代码编译出来的类, 这个问题就比较大了.

不知各位怎么看这个问题?
   发表时间:2006-10-31  
这种情况其实我就碰到过好几次吧,tomcat会抛出500 error的。

所以建议修改了servlet之后,还是restart一下tomcat。

1 请登录后投票
   发表时间:2006-10-31  
robbin 写道
这种情况其实我就碰到过好几次吧,tomcat会抛出500 error的。

所以建议修改了servlet之后,还是restart一下tomcat。


看来果然有实际的问题, 其实我是在考虑Servlet到底能多大程度的动态部署, 这个绊子着实不小.
0 请登录后投票
   发表时间:2006-11-01  
这个问题在号称可以热切换的 ErLang 上的处理方法如下:

http://erlang.org/doc/doc-5.5.1/doc/reference_manual/code.html#12.3

The code of a module can exist in two variants in a system: current and old. When a module is loaded into the system for the first time, the code becomes 'current'. If then a new instance of the module is loaded, the code of the previous instance becomes 'old' and the new instance becomes 'current'.

Bot old and current code is valid, and may be evaluated concurrently. Fully qualified function calls always refer to current code. Old code may still be evaluated because of processes lingering in the old code.

java 目前已经实现的动态部署功能还非常有限。
http://bugs.sun.com/bugdatabase/view_bug.do;:YfiG?bug_id=4910812
0 请登录后投票
   发表时间:2006-11-01  
stephen 写道
这个问题在号称可以热切换的 ErLang 上的处理方法如下:

http://erlang.org/doc/doc-5.5.1/doc/reference_manual/code.html#12.3

The code of a module can exist in two variants in a system: current and old. When a module is loaded into the system for the first time, the code becomes 'current'. If then a new instance of the module is loaded, the code of the previous instance becomes 'old' and the new instance becomes 'current'.

Bot old and current code is valid, and may be evaluated concurrently. Fully qualified function calls always refer to current code. Old code may still be evaluated because of processes lingering in the old code.

java 目前已经实现的动态部署功能还非常有限。
http://bugs.sun.com/bugdatabase/view_bug.do;:YfiG?bug_id=4910812


不过ErLang加载一个模块是系统行为, 但是往HttpSession里放对象就是应用行为了.
Servlet的这个问题似乎还是只能通过应用方面注意一些事项来完善.

我在考虑不是通过  session.setAttribute(key, obj); 去设置对象, 而是在应用自己某个类一个singleton的实例上加一个 Map<String,Object> dict; 通过 dict.put(session.getId(), obj); 来关联session级对象, 这样如果应用代码被重新加载, 这个Map也就会被重新初始化, 应用 get 到 null 以后重新做一下初始化. 不过目前还限于理论思考, 不知道实际中是不是行得通.
0 请登录后投票
   发表时间:2006-11-01  
会有 ClassCastException 的, 你取出来这个过程会失败, 即使你放在 session 里面这个对象的类没有被重新编辑, Reload之后由于 ClassLoader 不同了, 一样会抛出 ClassCastException.

要动态部署, 自己写 ClassLoader 最好: 自动重新加载-自定义ClassLoader初步

另外, 怎么做到"应用代码被重新加载, 这个Map也就会被重新初始化"? 似乎也没有什么好办法啊. 除非整个 APP 被重新加载, 否则这个 Map 为啥会被清空呢?
0 请登录后投票
   发表时间:2006-11-02  
glassprogrammer 写道
会有 ClassCastException 的, 你取出来这个过程会失败, 即使你放在 session 里面这个对象的类没有被重新编辑, Reload之后由于 ClassLoader 不同了, 一样会抛出 ClassCastException.

要动态部署, 自己写 ClassLoader 最好: 自动重新加载-自定义ClassLoader初步

另外, 怎么做到"应用代码被重新加载, 这个Map也就会被重新初始化"? 似乎也没有什么好办法啊. 除非整个 APP 被重新加载, 否则这个 Map 为啥会被清空呢?


以下摘自Servlet 2.3 Specification:
引用
SRV.3.7 Reloading Considerations
Although a Container Provider implementation of a class reloading scheme for ease
of development is not required, any such implementation must ensure that all
servlets, and classes that they may use2, are loaded in the scope of a single class
loader. This requirement is needed to guarantee that the application will behave as
expected by the Developer. As a development aid, the full semantics of notification
to session binding listeners should be be supported by containers for use in the
monitoring of session termination upon class reloading.
Previous generations of containers created new class loaders to load a servlet,
distinct from class loaders used to load other servlets or classes used in the servlet
context. This could cause object references within a servlet context to point at
unexpected classes or objects, and cause unexpected behavior. The requirement is
needed to prevent problems caused by demand generation of new class loaders.


为了满足这个要求, 容器如果用新的ClassLoader重新加载一个WebApp的其他部分, 那么上面提到的包含那个Map的这个类也会以这个新的ClassLoader被重新加载, 则这个Map应当随着定义它的类被重新初始化过了.

如果JVM被加强了, 可以支持同一个ClassLoader重新加载相同的类, 那么可以有另外的实现方式, 不过好像Dolphin(JDK7)里是不是做这个改进尚没有定论, 暂时应该不会有大变化了吧.
0 请登录后投票
论坛首页 Java企业应用版

跳转论坛:
Global site tag (gtag.js) - Google Analytics