JRuby

来自站长百科
跳转至: 导航、​ 搜索

JRuby,一个采用纯Java实现的Ruby解释器,由JRuby团队开发。它是一个自由软件,在CPL/GPL/LGPL三种许可协议下发布。主要开发者有Charles Nutter、Thomas Enebo、Ola Bini、Nick Sieger等。

简介[ ]

通过JRuby,你可以在JVM上直接运行Ruby程序,调用Java的类库。很多Java编写的Ruby IDE都是使用JRuby来解释语法的。 2006年SUN雇佣了两名JRuby团队的两名核心成员Charles Nutter和Thomas Enebo全职开发JRuby,后来ThoughtWorks也雇佣了一名JRuby项目的核心成员全职开发JRuby。

自此JRuby发展非常迅速,立刻推出一个50%性能提升的版本。最近又发布了0.9.8版,正式宣布官方支持Rails,单元测试有98%成功通过(也是因此称作0.9.8版),现在开发小组全力修复剩下的2%,将会很快发布100%支持Rails的JRuby 1.0。但是目前JRuby的主要精力集中在功能实现上,性能还不如理想,1.0发布之后应该就会全力解决性能问题。

历史[ ]

版本 发布日期 改进
0.9 2006-08-01 Rails支持
1.1 2008-03-28 比Ruby MRI 1.8.7性能更好
AOT模式JIT模式
1.1.4 2008-08-28
1.2.0 2009-03-16 提供对Ruby 1.9几乎完全支持 (包含JIT编译器)
初步的Android支持
1.3.0 2009-06-03 性能提升
1.4.0 2009-11-02 支持Ruby 1.8.7
Ruby 1.9支持的改进

使用jprofiler监控jruby脚本[ ]

jruby本质上也是启动一个jvm,然后去读ruby脚本并解释执行(也可以编译),因此jprofiler理所当然也可以去监控jruby脚本的执行。

执行[ ]

jruby hello.rb等价于执行:

java -xmx378m -xss1024k -djruby.home=/usr/local/jruby

-djruby.lib=/usr/local/jruby/lib djruby.script=jruby org.jruby.main hello.rb这一点,你可以通过ps aux |grep jruby 看到。因此配置jprofiler就简单了,在vm arguments加上这些参数(可以包括jruby的参数),比如本例中的vm arguments配置如下:

-server -xmx378m -xss1024k -djruby.script=jruby -djruby.thread.pooling=true
-djruby.jit.threshold=0 -djruby.compile.fastest=true
-djruby.home=d:jrubyjruby-1.1rc2 -djruby.lib=d:jrubyjruby-1.1rc2lib

main class or executable jar填上:org.jruby.main。然后就是arguments一栏填上你的脚本位置:

d:rubylibhello.rb

最后,别忘了将jruby/lib目录下的bsf.jar和jruby.jar加入class path。

可以用jprofiler去观察gc、线程和锁、heap等等了。

运行JRuby程序[ ]

JRuby的发行中带有一个tar.gz文件。在本例中,基于Windows系统并使用JRuby的jruby-bin-0.9.1.tar.gz二进制发行版本以及Java SE版本1.5.0_06。在解压这些发行文件后,会出现一个jruby-0.9.1文件夹,其中包含的子文件夹有:bin,docs,lib和samples。注意,你可以添加一个指向这个目录的JRUBY_HOME环境变量,然后把%JRUBY_HOME%bin(在UNIX系统上是$JRUBY_HOMEbin)添加到你的系统路径下。JRuby发行版的bin目录中包含一个jruby.bat文件,它用于运行JRuby解释器程序。从命令行下运行“jruby -version”可以测试JRuby是否正确工作:

C:JRubyjruby-0.9.1>jruby -version ruby 1.8.5 (0) [java] 

在上面的samples目录中,你可以找到一些展示JRuby功能的示例Ruby程序。作为第一个示例,你可以看一下下面这个java2.rb示例。这个示例包含了下列Ruby代码

require "java" 
filename = "./samples/java2.rb" 
fr = java.io.FileReader.new filename  
br = java.io.BufferedReader.new fr  
s = br.readLine  
print "------ ", filename, "------n" 
while s  
puts s.to_s  
s = br.readLine  
end 
print "------ ", filename, " end ------n";  
br.close 

第一行代码负责启动JRuby的Java支持并且允许一个Ruby程序使用Java

该程序定义了一个指向文件“./samples/java2.rb”的java.io.FileReader。然后,它声明了一个java.io.BufferedReader用于缓冲经由FileReader读取的数据。本文程序从这个文件中读取所有的代码并且把它们输出到控制台。下面是使用JRuby运行这个Ruby脚本的输出结果:

C:JRubyjruby-0.9.1>jruby .samplesjava2.rb  
------ ./samples/java2.rb------  
require "java" 
filename = "./samples/java2.rb" 
fr = java.io.FileReader.new filename  
br = java.io.BufferedReader.new fr  
s = br.readLine  
print "------ ", filename, "------n" 
while s  
puts s.to_s  
s = br.readLine  
end 
print "------ ", filename, " end ------n";  
br.close  
------ ./samples/java2.rb end ------  
C:JRubyjruby-0.9.1>

到现在为止,你已经能够使用JRuby运行一个Ruby脚本;该脚本能够使用Java类读取一个文件并且输出其内容。这是JRuby向Ruby用户展示的一个强有力的概念。

在JRuby中使用Java类[ ]

JRuby提供的最重要的方法是Kernel#include_class方法。这个方法允许Ruby按如下方式使用Java类:

require "java" 
# Include Java's FileReader  
include_class "java.io.FileReader" 
filename = "./samples/java2.rb" 
fr = FileReader.new filename

然而,有可能在Java类和Ruby类之间存在命名冲突问题。其中,字符串的使用就是一个例子;Java中提供了java.util.String,而Ruby中提供了Kernel::String。为了解决这个命名冲突问题,你可以在包括它时重命名这个类-通过把一个代码块传递给include_class方法调用来实现:

require "java" 
# Include Java's String as JString  
include_class("java.lang.String") { |package, name| "J" + name }  
s = JString.new("Hello World from JRuby!")  
puts s

通过定义一个包括Java类定义的Ruby模块,你还能够避免这个命名冲突:

require "java" 
module JavaLang  
include_package "java.lang" 
end 
s = JavaLang::String.new("Hello World from JRuby!")  
puts s

下面提供了一个示例程序,javaHello.rb,它使用Java的HashMap来存储三个字符串并且打印它们。这个程序中有趣的地方在于,它调用Ruby的java.util.Set(通过java.util.HashMap.keySet()方法调用返回)中的each方法。这允许把通过这个“each”方法返回的结果键传递给相应的代码块,然后该代码块使用该键取得相应的字符串,并且输出该字符串。

require "java" 
module JavaLang  
include_package "java.lang" 
end 
include_class("java.util.HashMap") { |pkg, name| "J" + name }  
s = JavaLang::StringBuffer.new("Hello Java World")  
puts s.append(", I love JRuby")  
m = JHashMap.new()  
m.put("java", "Java")  
m.put("ruby", "Ruby")  
m.put("jruby", "JRuby")  
puts m  
m.keySet().each { |key| puts m.get(key) }

下面是当使用JRuby运行它时的输出结果:

C:\JRuby>jruby javaHello.rb  
Hello Java World, I love JRuby  
{java=Java, ruby=Ruby, jruby=JRuby}  
Java  
Ruby  
JRuby  
C:\JRuby>

一个完全使用Java编写的类似上面的程序看起来如下所示:

StringBuffer s = new StringBuffer("Hello Java World");  
s.append(", I love JRuby");  
HashMap<String> m = new HashMap<String>();  
m.put("java", "Java")  
m.put("ruby", "Ruby")  
m.put("jruby", "JRuby")  
for (String key: m.keySet()) {  
 println(m.get(key));  
}

在JRuby中使用Swing[ ]

Swing是一个GUI框架,它允许开发者使用Java语言创建图形化应用程序。下面是一个示例程序,javaSwingHello.rb,它使用Java的Swing来打印一个消息:

require 'java' 
include_class "javax.swing.JFrame" 
include_class "javax.swing.JLabel" 
frame = JFrame.new()  
jlabel = JLabel.new("Hello from JRuby with Swing")  
frame.getContentPane().add(jlabel)  
# frame.content_pane.add(label)  
frame.pack()  
frame.setVisible(true)  
frame.visible = true

从命令行如下运行这个程序:

C:\JRuby>jruby javaSwingHello.rb 

一个带有文本“Hello from JRuby with Swing”的新窗口将会出现: Jruby1.jpg

总结[ ]

本条目提供一个JRuby语言的简介。JRuby允许现有Java开发者充分利用Ruby提供的强有力和易于使用的编程特点,而Ruby开发者将能够自由使用庞大的曾使Java广泛地应用于各个软件开发领域的Java库来进行开发。

相关条目[ ]

参考来源[ ]