Java 编程的动态性

Java 编程的动态性
参考资料:IBM开发者资料
参考地址 http://www.ibm.com/developerworks/cn/java/j-dyn0429/
一 类加载器
C语言程序执行过程:编译、链接(生成可执行文件)、操作系统的装载程序将其装入内存(建立进程)来运行
java程序的执行:编译、加载、在虚拟机中执行
新加载的类与其他类的链接由jvm来完成,所以java可以实现动态的链接,即在程序已经运行起来之后决定更新哪些模块、使用哪些模块(可以实现不停机而更新功能)。
java的这种机制与C++的dll的区别是,前者完全动态,允许在程序运行的时候改变代码的逻辑、后者所谓的动态在代码逻辑上来讲是静态的(使用的条件、功能的组合要硬编码)。
如:
用户输入了A 则加载A模块,否则不加载
这样一段逻辑,对于A模块而言它是动态的,但是对于加载的这个逻辑而言却是固定的

java的类加载器可以便于实现程序内的空间分离、增强程序的安全性和健壮性。如通过使用不同的加载器可以实现用户程序无法更改系统核心程序、也可实现多个用户空间共享代码(此部分代码放到上层加载器即可)。
这个估计是借鉴了OS中的内核空间和用户空间的概念,一个应用程序挂了很容易,但是想用一个应用程序来把整个OS搞挂(系统无法继续运行)不太容易。同样道理,在现实中想用一个java应用程序来搞挂jvm,好像也是
异常的艰难。如果要开发一个基础的框架(如新的脚本语言),那么如何来保证这种安全性就显得十分的重要。

二 反射(灵活、但是会影响性能)
jvm中的每个Class都有足够的hook让用户来用,所以如果你想改变一个初始化时设置的值成为可能(通过源代码的话只能硬编码)。另外、利用反射用户可以在代码中直接使用之前已经在JVM中实现的模块。
一个实际的使用场景:
假设 我用java实现了一种新的脚本语言 xxx,采用的是编译执行而不是解释执行(为了效率),那么我该如何实现 在XXX脚本中定义过的函数可以被后来的函数使用呢?
如果是解释执行很简单,记录每个内部提供的库函数和定义过的xxx脚本函数的地址,之后在解释新的xxx脚本函数调用时,依次hashmap到相应的函数即可。但是现在xxx脚本是编译型的,
我必须保证用户定义的XX脚本函数 aaa()要马上生效,即当扫描过aaa()之后就要求将它编译、不仅要编译、而且要链接到系统中(这样后面的xxx脚本bbb()中才能使用aaa()函数),由于要链接到系统中的代码是未知的,
要用到哪些其他的库也未知,所以C++是解决不了这个问题的(所以用C++实现的脚本都是解释型的)、而java的类加载器和反射就可以满足这种需要。
顺便说一下:有人认为java比C++慢,为什么还用java来实现脚本语言?java在运行时是否真的比C++慢我姑且不说(在使用JIT的情况下还真的不好说、而且C++可能快、但是我们写出来的C++却不一定快、和程序员
的水平有关系啊),要知道我们整个系统的速度是体现在脚本上的。同样的一个脚本函数aaa(),如果是用C++实现,那么我需要解释每一个语句,之后转化为内部定义的库函数指针、再之后才是真正的函数的执行。
而如果此脚本是用java实现的,那么我的每个脚本函数在运行时跑的都是.class文件,省去了每次都要解释指令的步骤,所以单从这里来看用java来实现脚本语言确实是可能更快的。除非我们相信自己可以做出来比jvm更牛X的虚拟机,不然我们有理由选择java来实现脚本语言。

三 修改byteCode
不仅用户可以使用jvm中已经载入的Class,用户甚至可以在JVM运行的过程中修改byteCode、并且将新的byteCode重新加载(类似于C里面的编译、连接、装载)
Javassist是一种可以改变bytecode的库、如可以在每个方法被调用前添加统计语句(bytecode的层面上)
PS:这种库适合于实现基础的平台,难怪现在基于java的平台如此之多

本文写于 2011年4月
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值