是什么让宝石与JRuby不兼容?

时间:2015-08-08 08:31:47

标签: ruby gem bundler jruby

我跑了bundle install,令我惊讶的是,Rails 4附带的大多数宝石安装得很好。 byebug是一个没有,但没什么大不了的。

究竟是什么让宝石与JRuby完全不兼容?

1 个答案:

答案 0 :(得分:3)

在这种特殊情况下,gem被编写为YARV的C扩展,因此它只适用于YARV,而不适用于任何其他Ruby实现,包括但不限于JRuby,Rubinius,MagLev,MRuby,IronRuby等。

令人遗憾的是:据我所见,它只使用公共Ruby API,它实际上并没有使用YARV VM的任何私有内部信息,所以它也可以用便携式编写红宝石。

通常,有几个原因可以解释为什么gem只能在一个特定的Ruby实现上工作:

  • 它使用主机平台的一些特定功能,并非所有Ruby实现都可用。例如,用Java编写的使用Java平台库的gem很可能不适用于YARV,只能使用JRuby。
  • 它访问特定Ruby实现的私有内部实现细节。我想这很明显。什么如此明显,即使在基于C的Ruby实现中也没有可移植的C API。什么通常被称为" Ruby C扩展API"真的只是YARV裸露它的内部。 Rubinius和JRuby都为YARV开发了大量的工作开发仿真层,因此至少有一些C扩展可以工作,但这很难。例如:YARV的垃圾收集器非常简单,它永远不会在内存中移动对象。许多C扩展依赖于此,但对于像Rubinius或JVM的现代GC而言,这根本不是这样。 YARV不允许多个Ruby线程同时运行,许多C扩展依赖于此,但对于几乎所有其他Ruby实现而言,情况并非如此。等等......另外,那些仿真层很慢。真的很慢。对于已经用C语言重写的宝石而言,完全有可能获得性能"在JRuby或Rubinius上运行速度比纯Ruby对手慢。 (毕竟,在某些情况下,Rubinius已经可以与CEg竞争Rubinius中的Hash类是用Ruby编写的,并且与用Y编写的YARV Hash类相似。 )
  • 它使用特定实现中缺少的Ruby功能。例如,Refinements被广泛批评为在执行方法查找的积极优化的实现中是不可实现的(或者更准确地说:精炼,它们当前指定的方式,使得不可能应用这些优化)。精炼的设计者都碰巧是YARV开发人员,在那里并不重要,因为YARV无论如何都不能优化方法查找,例如, JRuby开发人员决定不实施Refinements。 (10年前,他们对延续做了同样的事情。)因此,如果一个宝石使用Refinements,它就不会在JRuby上工作。

Rubinius和JRuby开发人员开发了一个FFI API,可用于以可在许多Ruby实现中移植的方式从Ruby获得C API。 Rubinius,JRuby,MacRuby和(我相信)MagLev原生支持FFI,而对于YARV,有一个宝石可以为它添加FFI支持。使用独立于实现的FFI API而不是YARV API的gem应该适用于几乎所有的实现。但是,FFI API并没有提供对实现内部的访问(显然),因此对于某些宝石来说它是不可用的。例如,有些宝石试图让您访问Proc的源代码,这是高度特定于实现的(甚至可能无法工作,例如,当您提前编译到带有.class的Java jrubyc文件,源代码甚至不存在于运行时),因此每个Ruby实现都必须有不同版本的gem。