`
fsword
  • 浏览: 164495 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
社区版块
存档分类
最新评论

[翻译] JRuby class loader by example

 
阅读更多

大家都知道,JRuby可以用 require 来装载 jar 文件,但是似乎很少有人知道有另外两种方法可以完成同样的事情,也很少有人知道(JRuby)底层是如何做的。JRuby官方的 wiki 页面 包含了一组例子以帮助大家学习这些,不过,也许还可以更进一步......

 

如前所述,在你的ruby应用中装载java类的首要方法是 require 。它的工作方式与对 ruby 文件的装载类似,只是装载目标变成了jar文件,可以用类似下面的代码装载(jar文件中被打包的)java类:

 

 

require 'java'
require 'hello_world.jar'

 

然而,这种方式只是让我们装载jar文件,它不能用于装载存放众多类文件的classes目录。

 

第二种方式是使用 $CLASSPATH 这个全局变量,这个方式很类似我们在 $LOADPATH 全局变量上增加或者去除路径。这个方法的好处是可以添加一个存放类文件的目录,你可以试试下面的代码

 

require 'java'
$CLASSPATH << 'hello_world.jar'
$CLASSPATH << 'hello_world_directory'

 

如果我们想深入了解这两种方法(require和$CLASSPATH),我们将发现,require实际上最终还是把我们要装载的jar文件添加到了 $CLASSPATH 上:

 

 

$ irb
jruby-1.6.0.RC2 :001 > require 'java'
 => true
jruby-1.6.0.RC2 :002 > require '/Users/david/dev/jruby/lib/jruby.jar'
 => true
jruby-1.6.0.RC2 :003 > $CLASSPATH
 => ["file:/Users/david/dev/jruby/lib/jruby.jar"]

 

第三种方法可能是最少被人所知的,在我们使用jruby的环境时,我们可以访问一个叫做JRuby的常量,而在这个常量中,有一些东西可以帮助程序员访问JRuby的运行时环境,在这里,我们能够接触到JRuby进行java类装载的 class loader:  JRuby.runtime.jruby_class_loader ,代码示例如下:

 

 

require 'java'
F = java.io.File
class_loader = JRuby.runtime.jruby_class_loader

class_loader.add_url(F.new('hello_world_directory').to_url)
class_loader.add_url(F.new('hello_world.jar').to_url)

 

看看这里的代码 ,我们可以发现,当我们将一些东西添加到 $CLASSPATH 常量上去的时候,我们实际上是在将这些东西添加进JRuby的class loader:

 

@JRubyMethod(name = {"append", "<<"}, required = 1)
public IRubyObject append(IRubyObject obj) {
    String ss = obj.convertToString().toString();
    try {
        URL url = getURL(ss);
        getRuntime().getJRubyClassLoader().addURL(url);
    } catch (MalformedURLException mue) {
        throw getRuntime().newArgumentError(mue.getLocalizedMessage());
    }
    return this;
}

 

好了,现在的问题是,我们应该使用哪种方式(去装载java类)呢?对于日常的情况,最好的方式显然是 require——我们使用的大多数java 代码都是被打包成一个jar文件的,而且,这也是我们都知道的语法。如果我们需要的java类文件存放在目录中或者我们有一些很特殊的场景,可能更好的选择是设置 $CLASSPATH ,它也能满足我们的需要,而且我们还不必与url和java方言(指class loader这种很java的东西)打交道,同时,这也是一个我们都知道的语法。最后,第三个方案适合那些需要清晰界定 class loader 的场景中。例如,在Trinidad中,我就用了这个方案,这里,每一个被部署的应用需要装载自己的jar文件,第三个方案可以让我针对每个应用建立新的class loader并保证这些class loader之间是完全隔离的。

 

0
1
分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics