`
Dustin
  • 浏览: 310987 次
  • 性别: Icon_minigender_1
  • 来自: 广州/成都
社区版块
存档分类
最新评论

java动态代码的实现以及Class的卸载

阅读更多

 JavaWorld一篇题为 Add dynamic code to your application 的文章介绍了如何使用动态代理技术使普通的java源代码具有像jsp一样的动态编译效果,十分有趣。
  使用过jsp技术的程序员都知道,应用部署以后,我们是可以直接修改jsp源文件的。当客户请求这个被修改过的jsp文件时,web容器会自动监测出该jsp文件已经被更新,因此重新编译该jsp文件,向客户返回最新的信息。但是,对于一般的java源文件,如果我们仅仅修改源文件,而不重新编译部署的话,web容器是不会处理的。
   那我们可不可以让普通的java源文件也具有jsp一样的效果呢,也就是说,程序在运行过程中,我们一旦修改某个类的源文件,程序会自动监测出来,并重新编译该文件,同时进行重新连接,动态更新。答案是肯定的,而且方法并不复杂。主要思想是当执行一个接口的操作时,我们使用动态代理技术将其拦截,然后监测实现该接口的类的源文件是否已经更新,如果没有更新,则把方法交给相应的对象的方法执行,否则,我们重新编译该类的源文件,同时重新加载该类,然后,我们就可以通过该类获得最新的对象以执行相应的操作了。
    系统的总体架构是是一个Dynamic Proxy,而实现的重点是捕捉到接口方法时在调用invoke的时候如何动态编译和重新加载。编译我们可以使用java提供的com.sun.tools.javac.Main.compile方法(要将jdk lib目录下的tool.jar加入到classpath中),通过该方法我们可以将指定的源文件进行编译并将相应的class文件放置到指定的目录中。
     为了能够进行重新连接,我们必须要把原来已经被加载的类卸载,否则我们是不能够将最新的类加载到jvm中去的。但是,我们卸载时却不能指定把classloader装载的类中的某一个类卸载掉,因此,我们只好重新生成一个classloader,通过它来重新加载我们新编译好的class文件。在这里,URLClassLoader是一个很好的选择。

 

updated(2009-3-16):

   JVM中的Class只有满足以下三个条件,才能被GC回收,也就是该Class被卸载(unload):

   - 该类所有的实例都已经被GC,也就是JVM中不存在该Class的任何实例。
   - 加载该类的ClassLoader已经被GC。
   - 该类的java.lang.Class 对象没有在任何地方被引用,如不能在任何地方通过反射访问该类的方法.

分享到:
评论
20 楼 liuInsect 2012-08-31  
其实你没有说到“怎么卸载一个class文件”啊,只是说怎么让他被GC,但是GC的本身就是不确定的,有没有可以直接指定 “马上将class卸载掉”的方法呢?
19 楼 juyin 2007-01-15  
JDK6.0中加入对脚本语言的支持也应该有这种的考虑吧,只是由于脚本是解释执行的,比较好处理。
感觉还是有一定的应用场景
有没有更详细的资料?
18 楼 boogie 2007-01-14  
kdekid 写道
Dustin 写道
引用
PermGen space 是 hotspot 存放永久生成(permanent generated)的数据的空间,包括类、intern string等


Tomcat等JSP容器都支持热部署,它们是否存在这样的问题?如果存在,它们是使用什么机制解决的呢?没有深入研究过Tomcat,迷惑中。

一个最典型的例子是,你在IDE中(包括 netbeans 和 ecilpse)不断 restart 某个webapp,特别是用到了 spring/hibernate 的 webapp,就会出现这个 error。这可能是由于 spring 对程序结束的清除工作做得不是很好。在实际的部署中,基于 spring 的程序如果单是重新deploy而不是重新启动应用服务器,也会出现类似情况。

的确如此!
17 楼 歆渊 2007-01-14  
zkj_beyond 写道
jsp和java类是完全不一样的概念。

jsp->servlet 在web容器中,你的servlet是单例的,也是无状态的,线程安全的。也就是只有一个对象,
jsp改变以后,web容器只要把相应的servlet对象更新就好了。


而java呢?
可能这个类在你的应用中有n个实例,与这些实例单向,双向关联的又有n个实例。如果你修改了,这些jvm存在的老的实例对象怎么办????

java这类静态语言无法实现象asp,php,jsp的效果的。

同意, 动态替换代码必需重新构造新的对象实例才能生效, 所以基本上只有是无状态对象在容器中执行的情况下才有现实意义.
16 楼 zkj_beyond 2007-01-13  
jsp和java类是完全不一样的概念。

jsp->servlet 在web容器中,你的servlet是单例的,也是无状态的,线程安全的。也就是只有一个对象,
jsp改变以后,web容器只要把相应的servlet对象更新就好了。


而java呢?
可能这个类在你的应用中有n个实例,与这些实例单向,双向关联的又有n个实例。如果你修改了,这些jvm存在的老的实例对象怎么办????

java这类静态语言无法实现象asp,php,jsp的效果的。
15 楼 YuLimin 2007-01-13  
代理,面向接口编程
public interface Postman {
	
	void deliverMessage(String msg);
}


这个容易做到,难的是有没有办法做到动态接口动态实现之类的呢?
这在得Class.forName了?还是另有它法?
14 楼 Dustin 2007-01-12  
引用
那就研究一下,楼上的!


嗯,有机会的话一定会。
13 楼 Godlikeme 2007-01-12  
magice 写道
Godlikeme 写道
动态加载class 不是什么好主意,可以说是一个馊主意。
为什么不具体说说为什么是一个馊注意呢!

3年前就做过一个自动测试机,用的是动态生成unit Test类的测试逻辑,然后动态编译加载自动执行测试,对于这样的小工具还可以。再有就是热部署了。
对于应用来讲,是一个不顾一切的捣洞技术,带来了系统运行不稳定的一系列问题。比如SPRING框架下beanFactory肯定会有问题。
12 楼 hing007210 2007-01-12  
比较有创意,收藏
11 楼 galaxystar 2007-01-12  
那就研究一下,楼上的!
10 楼 kdekid 2007-01-12  
Dustin 写道
引用
PermGen space 是 hotspot 存放永久生成(permanent generated)的数据的空间,包括类、intern string等


Tomcat等JSP容器都支持热部署,它们是否存在这样的问题?如果存在,它们是使用什么机制解决的呢?没有深入研究过Tomcat,迷惑中。

一个最典型的例子是,你在IDE中(包括 netbeans 和 ecilpse)不断 restart 某个webapp,特别是用到了 spring/hibernate 的 webapp,就会出现这个 error。这可能是由于 spring 对程序结束的清除工作做得不是很好。在实际的部署中,基于 spring 的程序如果单是重新deploy而不是重新启动应用服务器,也会出现类似情况。
9 楼 Dustin 2007-01-12  
引用
PermGen space 是 hotspot 存放永久生成(permanent generated)的数据的空间,包括类、intern string等


Tomcat等JSP容器都支持热部署,它们是否存在这样的问题?如果存在,它们是使用什么机制解决的呢?没有深入研究过Tomcat,迷惑中。
8 楼 kdekid 2007-01-12  
dwangel 写道
调试的时候还是有点用的,webwork的quick start也有这方面的功能。

引用

jvm存放生成的class的heap是有限的,而一部分过去的class还存在引用而不会被gc。所以这样做最后的后果是导致 java.lang.OutOfMemoryError: PermGen space。

如果仅仅是动态加载同一个类的更新版本呢?

如果旧的类的引用依旧存在,始终会内存不足的。hotspot 的机制就是如此,这是改不了的。PermGen space 是 hotspot 存放永久生成(permanent generated)的数据的空间,包括类、intern string等。
7 楼 LucasLee 2007-01-12  
虽然没有想出它合适的应用场景,
但是新颖的思路挺不错的.
说不定什么时候会用得上,留个印象先,挺好.
6 楼 adamzhao 2007-01-12  
<br/>
<strong>Dustin 写道:</strong><br/>
<div class='quote_div'> JavaWorld一篇题为 <a href='http://www.javaworld.com/javaworld/jw-06-2006/jw-0612-dynamic.html'>Add dynamic code to your application</a> 的文章介绍了如何使用动态代理技术使普通的java源代码具有像jsp一样的动态编译效果,十分有趣。<br/>
  使用过jsp技术的程序员都知道,应用部署以后,我们是可以直接修改jsp源文件的。当客户请求这个被修改过的jsp文件时,web容器会自动监测出该jsp文件已经被更新,因此重新编译该jsp文件,向客户返回最新的信息。但是,对于一般的java源文件,如果我们仅仅修改源文件,而不重新编译部署的话,web容器是不会处理的。<br/>
   那我们可不可以让普通的java源文件也具有jsp一样的效果呢,也就是说,程序在运行过程中,我们一旦修改某个类的源文件,程序会自动监测出来,并重新编译该文件,同时进行重新连接,动态更新。答案是肯定的,而且方法并不复杂。主要思想是当执行一个接口的操作时,我们使用动态代理技术将其拦截,然后监测实现该接口的类的源文件是否已经更新,如果没有更新,则把方法交给相应的对象的方法执行,否则,我们重新编译该类的源文件,同时重新加载该类,然后,我们就可以通过该类获得最新的对象以执行相应的操作了。<br/>
    系统的总体架构是是一个Dynamic Proxy,而实现的重点是捕捉到接口方法时在调用invoke的时候如何动态编译和重新加载。编译我们可以使用java提供的com.sun.tools.javac.Main.compile方法(要将jdk lib目录下的tool.jar加入到classpath中),通过该方法我们可以将指定的源文件进行编译并将相应的class文件放置到指定的目录中。<br/>
     为了能够进行重新连接,我们必须要把原来已经被加载的类卸载,否则我们是不能够将最新的类加载到jvm中去的。但是,我们卸载时却不能指定把classloader装载的类中的某一个类卸载掉,因此,我们只好重新生成一个classloader,通过它来重新加载我们新编译好的class文件。在这里,URLClassLoader是一个很好的选择。</div>
<p> </p>
<p> </p>
<p>热部署还是很有用的,只是实施方案需要斟酌一下。<br/>
<br/>
<br/>
<br/>
</p>
5 楼 dwangel 2007-01-12  
调试的时候还是有点用的,webwork的quick start也有这方面的功能。

引用

jvm存放生成的class的heap是有限的,而一部分过去的class还存在引用而不会被gc。所以这样做最后的后果是导致 java.lang.OutOfMemoryError: PermGen space。

如果仅仅是动态加载同一个类的更新版本呢?
4 楼 lamono 2007-01-12  
感觉没必要~!
3 楼 magice 2007-01-12  
Godlikeme 写道
动态加载class 不是什么好主意,可以说是一个馊主意。
为什么不具体说说为什么是一个馊注意呢!
2 楼 Godlikeme 2007-01-11  
动态加载class 不是什么好主意,可以说是一个馊主意。
1 楼 kdekid 2007-01-11  
jvm存放生成的class的heap是有限的,而一部分过去的class还存在引用而不会被gc。所以这样做最后的后果是导致 java.lang.OutOfMemoryError: PermGen space。

相关推荐

    Java虚拟机JVM类加载初始化

    4):从java源代码文件动态编译成为class文件 当一个类被加载、连接、初始化后,它的生命周期就开始了,当代表该类的Class对象不再被引用、即已经不可触及的时候,Class对象的生命周期结束。那么该类的方法区内的...

    深入Java虚拟机(原书第2版).pdf【附光盘内容】

    第5-20章深入描述了java技术的内部细节,包括垃圾收集、java安全模型、java的连接模型和动态扩展机制、class文件、运算及流程控制等等,其中等6章和附录a-c完全可以作为class文件和指令含集的参考手册。本书还附带...

    JSP动态网页制作基础培训教程源代码.rar

    12 SampleServlet4.java 第7章 Servlet调用JavaBean示例java代码 13 SampleServlet4.class 第7章\ch7\WEB-INF\classes\ch7 Servlet调用JavaBean示例java类文件 14 web.xml 第7章\ch7\WEB-INF 第7章程序应用的描述...

    JD-GUI-java反编译工具 | windows版本

    JD-GUI是一个独立的图形实用工具,显示Java源代码 " . class文件。您可以使用JD-GUI浏览重新构建的源代码 用于即时访问方法和字段。 JD-GUI对非商业用途是免费的。这意味着JD-GUI不应该是 包含或嵌入到商业...

    深入Java虚拟机

    2.3.7 Java平台实现中的bug 2.3.8 测试 2.4 平台无关的七个步骤 2.5 平台无关性的策略 2.6 平台无关性和网络移动对象 2.7 资源页 第3章 安全 3.1 为什么需要安全性 3.2 基本沙箱 3.3 类装载器...

    深入java虚拟机第二版

    2.3.7 Java平台实现中的bug 2.3.8 测试 2.4 平台无关的七个步骤 2.5 平台无关性的策略 2.6 平台无关性和网络移动对象 2.7 资源页 第3章 安全 3.1 为什么需要安全性 3.2 基本沙箱 3.3 类装载器体系结构 ...

    深入JAVA虚拟机(第2版)

    2.3.7 Java平台实现中的bug 2.3.8 测试 2.4 平台无关的七个步骤 2.5 平台无关性的策略 2.6 平台无关性和网络移动对象 2.7 资源页 第3章 安全 3.1 为什么需要安全性 3.2 基本沙箱 3.3 类装载器...

    class加密,java加密,jar加密-Web虎 1.3

    Web虎是B/S软件源码、版权、数据综合保护系统,由深圳易用研发团队利用Windows内核驱动结合钥匙盘实现,已为深圳CRM领导厂商-讯盟软件、成都思必达、湖州金蝶、北京acewill等厂商的系列产品提供可靠保护. ...

    JShrink v2.32 特别版(KG)

    可以反编译出Java Class的源代码,并对其进行优化,达到缩减Class文件大小的目的 使用说明: 1.首先请确认你的电脑中已经卸载了此程序的旧的版本! 2.运行Setup目录中的程序安装原版程序! 3.运行Setup/KG目录中...

    整理后java开发全套达内学习笔记(含练习)

    Annotation [java] 代码注释 [ænәu'teiʃәn] anonymous adj.匿名的[ә'nɒnimәs]'(反义:directly adv.直接地,立即[di'rektli, dai'rektli]) apply v.应用,适用 [ә'plai] application n.应用,应用程序 [,æ...

    详解JAVA类加载机制(推荐)

    代码编译由JAVA源码编译器来完成。主要是将源码编译成字节码文件(class文件)。字节码文件格式主要分为两部分:常量池和方法字节码。 二、类加载 类的生命周期是从被加载到虚拟机内存中开始,到卸载出内存结束。...

    SmaliInjector20170719

    编辑静态类源文件:SmaliInjector\android\StaticClass.java,这个类将会被包进目标apk中 5). 编辑注入器源文件:SmaliInjector\pc\Injector.java,这是注入器关键文件,作用是调用ow2.asm来对目标jar中特定类的...

    Visual C++实践与提高-COM和COM+篇『PDF』

    2.5.5 对象代码的动态卸载 2.5.6 自动注册 2.5.7 例程实现 2.5.7.1 修改接口文件 2.5.7.2 修改对象程序 2.5.7.3 修改客户程序 2.6 为COM对象添加多接口支持 2.6.1 多接口 2.6.2 DEFINE_GUID 2.6.3 例程实现 2.6.3.1 ...

    asp.net知识库

    卸载Class? Web Form 窗体 如何实现web页面的提示保存功能 在ASP.Net中两种利用CSS实现多界面的方法 如何在客户端调用服务端代码 页面一postback,它就显示页面的最顶端,怎样让它定位在某一位置? 如何保证页面刷新...

    xheditor-1.1.14

    如果想实现更加复杂的交互应用,或者希望xhEditor编辑器能够和自己的Javascript代码实现互相访问,那么你可以选择使用方法2,相对具有更大的自由空间。 xhEditor也提供了即时的卸载编辑器方法: $('#elm1')....

    新版Android开发教程.rar

    � 源代码完全开放,便于开发人员更清楚的把握实现细节,便于提高开发人员的技术水平,有利于开发 出 更具差异性的应用。 � 采用了对有限内存、电池和 CPU 优化过的虚拟机 Dalvik , Android 的运行速度比想象的要...

    matlab对图像取反代码-tools:此存储库的目的是充当USCGA网络团队自行构建或使用的工具的存档

    matlab对图像取反代码托管工具和列表 该存储库的目的是充当我们网络团队自行构建或使用的工具的存档。 工具参考 音频文件(,等)。 朱利安的最低有效位代码 ...轻松查看音频文件的 隐写术 ...模块可从视频中获取长...

    汪文君高并发编程实战视频资源全集

    │ 高并发编程第一阶段20讲、同步代码块以及同步方法之间的区别和关系.mp4 │ 高并发编程第一阶段21讲、通过实验分析This锁的存在.mp4 │ 高并发编程第一阶段22讲、通过实验分析Class锁的存在.mp4 │ 高并发编程...

    汪文君高并发编程实战视频资源下载.txt

    │ 高并发编程第一阶段20讲、同步代码块以及同步方法之间的区别和关系.mp4 │ 高并发编程第一阶段21讲、通过实验分析This锁的存在.mp4 │ 高并发编程第一阶段22讲、通过实验分析Class锁的存在.mp4 │ 高并发编程...

    C#微软培训资料

    18.2 在 C #代码中调用 C++和 VB 编写的组件 .240 18.3 版 本 控 制 .249 18.4 代 码 优 化 .252 18.5 小 结 .254 第五部分 附 录 .255 附录 A 关 键 字.255 附录 B 错 误 码.256 附录 C .Net 名字空间...

Global site tag (gtag.js) - Google Analytics