选择合适的java脚本语言

选择合适的java脚本语言
--如果你正考虑在java应用中集成脚本解释器,最难得是决定使用那种

摘要:脚本语言已经向java开发者证明了它的价值。它让客户实现应用功能的扩展和界面的个性化,从而程序的价值得以提升。另外,它们可以显著的简化程序开发者的设计任务,通过实现动态定义、装载和评估。对于开发人员,集成一种或多种脚本语言的任务是简单的,从越来越长的可选列表中选出一个确实困难的。本文描述了一些伴随java应用中脚本语言支持的问题,并从不同角度比较了Groovy, JudoScript, Pnuts, JRuby, Jacl, Jython, Rhino和Beanshell,以期能帮助读者作出正确的决定。

三年前,我在javaworld写了一遍叫做“JavaScripting语言,那种是适合你的?”的文章。当我收集解释器并进行比较时,我尽量选择那些看起来满足苛刻商务需求的。理想状态下,我希望解释器能够方便的扩展应用的用户接口,并且有易读的脚本代码,高可靠,快速,有好的支持和文档,并且是完备的。在那个时候,我把列表限制到了Jacl,Jython,Rhion和BeanShell。

过去的三年中发生了很多变化。可选项不再是很少的几个,不管是动态开发还是直接选择,可选的脚本语言都有一打以上。可靠的选择列表比三年前增多了,现在还包括了Groovy, JudoScript, Pnuts和BeanShell。我们还可以考虑不再这个列表中的其他解释器,但这个列表中,已经足够开发人员自己的所需了。

我准备标准化所有解释器,看看Jacl, Jython, Rhion和BeanShell在2002年后性能有没有提高,并看看Groovy, JudoScript, Jruby和Pnuts同它们比较起来会怎样。我认为,看看不同脚本语言有什么独特之处,有什么特别的强项和弱点是很有意思的事情。

商务风险

在以前的文章里,我讲述了一些著名的优秀脚本解释器的资料,并说明了结合脚本解释器时你可能遇到的风险。本文中,我把这些内容简化为一些要点,并根据我在写那些文章之后的经验进行了改进。Java脚本解释器的优点是毋庸置疑的。使用脚本语言编码比使用java简单;脚步语言使程序的应用逻辑和用户界面的推动(drive/驱动?)和扩展成为可能;脚本代码可以违反java应用中类接口而运行,这是非常强大的功能。这样可以容易的编写程序测试驱动(write test drivers against your program),与编码并编译用于java类的单元测试相比,这是更加快速的。另外,如果用户花时间使用脚本扩展你的应用,他们就作你的工具上进行了投资,这使得你在竞争中多了一件利器。

但是,当在应用中集成jiava脚本解释器时,你必须面对一定的风险。两个主要的风险是,解释器可能成为孤儿,或者是当你把产品装上后,你可能发现解释器的致命缺陷。大多数解释器是通过开源模型动态维护和更新的,在这种情况下,你可以向研究你所发现问题的专家寻求帮助,给解释器打补丁,或者在未来版本中包含你需要的bug-fix(bug修理?)。这是一种安全的赌博,但并不能得到足够保证。如果你正严肃的考虑采用某个特定的解释器,请先看看它的开发站点,看看它的代码的进化,看看上面的流言板,用户的提问都有答案否。这可以帮助你了解代码支持的实际情况。

自我保护的另一格措施是,对你准备采用的任脚本何解释器进行完全测试。一些解释器在发布时包含了一个单元测试集。在测试你的应用中集成的解释器时,这些单元测试可以作为你的更大的测试集中的一部分。在测试解释器和应用之间的集成时,可以剔出自己的工作(you have your work cut out for you),因为脚本解释器有足够的弹性,并向开发人员暴露了足够的功能。你在早期向质量保证投入时间,而不是在应用已经成为产品,当用户需要急切的bug修复时才考虑。

新的竞争者列表

如果你正在寻找一个脚本解释器,你有很多选择。一些解释器支持已经存在的语言,比如Ruby, Python, JavaScript, Java和Tcl。另外一些解释器,如JudoScript, Groovy和Pnuts,选择了它们自己的类似java的语言语法。在比较不同的解释器,需要进行的最大的选择是,那种脚本语言的语法能很好的适合你的应用。像这种个人偏好发生作用的技术选择,可能在不同的开发人员团队引起激烈的争论。也许本文能有助于解决一些争论。

我收集比较了最近发布的八种不同的脚本解释器。解释器及其版本都在下表中列出。如果你对这些解释器并不熟悉,我还给出了每种解释器功能和开发活动的概要(a thumbnail sketch)。

脚本语言

版本号

简短描述

Jacl

1.3.1

Tcl解释器的java实现。如果你希望在脚本中使用工具包来创建用户接口类,看看Swank工程中的包裹(wrap)java swing 工具的类集。Jacl已经存在较长时间了,并且还在持续改进。

Jython

2.1

Python解释器的java实现。我注意到的一个问题是,已经有很长一段时间没有看到这个解释器的新版本了。但在Jython的网站上,说明了改变这种现状的计划,并且有基金支持。

Rhino

1.6.1

JavaScript解释器的java实现。它还支持把脚本编译成类文件。它的最新版本在几个月前发布,并加入了xml支持。

JRuby

0.8

Ruby解释器的java实现。它正在发展中,其测试版0.8表现良好。

BeanShell

2.0 beta 2

它是一个java源文件解释器,正在持续的发展和加入新特性。2.0版本提供了完全的普通java源文件解释支持。

Groovy

1.0 beta 9

Groovy是把Python和Ruby的特征加入java类似语法形成的,由很多令人兴奋的特征。可以把脚本直接编译成类文件,对不同的IDE,又很多Groovy插件可供选择,JSR委员会正在制定Groovy的规范。

JudoScript

0.9

它有和JavaScript类似的编程语法,学习和使用更加容易。在它的FAQ中提到了它的一个明确目标:“支持对象级,操作系统级和应用级的脚本”。我测试的0.9版运行良好。

Pnuts

1.1 beta 2

Pnuts有和java相似的编程语法,并保持持续更新。它可以把脚本直接编译成java类文件。

第一个指标:性能

未来测试第一项指标,我为每个解释器编写了等价的脚本代码,让他们完成简单的任务集并记录它们执行脚本所花的时间。我的测试脚本主要关注基本操作,如循环,整数比较和大的一维、二维数组分配和初始化。用于各个解释器的测试脚本和运行它们的java程序可以在原文资源部分下载。

在基准测试中最有用的信息是,解释器完成简单任务速度的apples-to-apples比较。如果你重点考虑吞吐量,基准数将十分重要。对每种脚本语言,我尽力编写相识的测试代码。测试使用Java1.4.2在东芝Tecra8100笔记本上运行,CPU为PIII700MHz,内存256MB。启动JVM时使用了默认的堆尺寸。出于向你展示解释器到底有多快还是多慢的兴趣,我编写了测试用例的java代码,并在java1.4.2上运行了。测试集包括:

1到1,000,000的计数

1,000,000次整数相等比较

分配并初始化包含100,000个元素的数组

分配并初始化一个500*500的二维数组

在2002年后有提高么?

在告诉你哪个解释器最快之前,我们先看看图1,这个条状图列出了很多耗时任务的结果:1百万次整数相等比较。对2002年文章中讲述的4种脚本解释器,我给出了在Java1.3.1JVM和Java1.4.2上运行所需的时间。非常有趣的是,测试Jython时用的是同一个版本的脚本解释器,结果表明新版JVM上速度提升了25%。在加上我使用了和前一次测试完全相同的硬件,所以可以肯定JVM1.4.2减少了运行基础测试所需的时间。现在看看Rhino,BeanShell和Jacl发生了什么:新版Rhino在1.4.2的JVM上比在1.3.1的JVM上运行的旧版本快乐86%,Jacl的这个数字是76%。可以看出,性能提高了很多。



四项任务的总时间

由于解释器在速度方面都十分相似(至少对我的基准测试是这样),我把各解释器完成四项基准测试所耗的总时间算出来并在图2中给出。



多变的标志

对这些简单测试,Rhino,Pnuts和Jytho始终是最快的,紧跟在后面的时Groovy,然后是JudoScript,然后是其他的。这些性能参数对你是否有用,取决于你希望脚本语言做的事情。如果你的脚本函数包含大量的迭代,并且用户要等待结果,你就需要关注速度最快的解释器,或者你就该考虑用java实现高性能要求的算法,而不是脚本代码。如果你的脚本只需要很少的重复操作,这些解释器速度的差异就不是那么重要了,快速的硬件也会使问题变得不同。

还有一点需要指出的是,即使最快的解释器,完成上面测试所用的时间也是同样功能java代码所用时间的大约40倍。如果速度是你最主要的问题,你必须清楚,最有意义的事情是用java代替脚本代码实现关键算法。

一些脚本解释器支持脚本代码直接编译成字节码。我对这将会产生多大的性能差异非常好奇,所以我进行了另一项测试。我用Rhino脚本解释器把基准测试脚本编译成了字节码,然后我把整个基准测试集用脚本和脚本产生的字节码分别运行了10遍。令人惊奇的是,与直接运行脚本相比,脚本码编译成字节码再运行仅仅节省了10%的时间。我最初任务,JVM的魔咒占用了运行测试集的大部分时间,但进一步的检查发现JVM魔咒本身只占测试集运行总时间的20%。简单脚本代码编译成字节码看起来会有积极的意义,但这并不一定是显著提高性能的银弹。也许在更长的或者,更加计算中心的脚本中,会看到不同的结果。

第二个标准:集成难度

第三个标准:许可证

英文原文:

http://www.javaworld.com/javaworld/jw-03-2005/jw-0314-scripting.html
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
Lua脚本语言可以通过Java调用,也可以在Lua中调用Java方法。在Java中使用Lua脚本语言,可以通过LuaJ库来实现。LuaJ是Lua的一个Java版本的实现,它允许在Java程序中调用Lua程序,并在Lua程序中调用Java程序,提供了方便的脚本功能。你可以使用以下步骤在Java中使用Lua脚本语言: 1. 导入LuaJ库:在你的Java项目中,你需要引入LuaJ库的依赖。可以通过在pom.xml文件中添加以下依赖关系来完成: ``` <dependency> <groupId>org.luaj</groupId> <artifactId>luaj-jse</artifactId> <version>3.0.1</version> </dependency> ``` 2. 初始化Lua运行时环境:使用Globals类创建一个Lua运行时环境。Globals是LuaJ库中的一个类,它提供了加载和运行Lua脚本的功能。 3. 加载Lua脚本:使用Globals的loadfile方法加载Lua脚本文件。loadfile方法将返回一个LuaValue对象,该对象代表了Lua脚本的函数。 4. 运行Lua脚本:通过调用LuaValue对象的call方法来运行Lua脚本。你可以传递参数给Lua脚本,并且可以从Lua脚本中获取返回值。 以下是一个示例代码,演示了如何在Java中调用Lua脚本: ```java import org.luaj.vm2.*; import org.luaj.vm2.lib.jse.*; public class LuaScriptRunner { public static void main(String[] args) { String script = "hello.lua"; // 指定Lua脚本文件 // 初始化Lua运行时环境 Globals globals = JsePlatform.standardGlobals(); // 加载Lua脚本 LuaValue chunk = globals.loadfile(script); // 运行Lua脚本 chunk.call(LuaValue.valueOf(script)); } } ``` 请注意,以上代码中的`hello.lua`是一个示例的Lua脚本文件名,你需要根据实际情况替换为你要调用的Lua脚本文件名。 你还有其他问题吗?
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值