什么使gem与JRuby不兼容?

什么使gem与JRuby不兼容?,ruby,gem,bundler,jruby,Ruby,Gem,Bundler,Jruby,我运行了bundle安装,令我惊讶的是,安装了Rails 4的大多数Gem都很好byebug不是这样,但没什么大不了的 是什么使gem与JRuby完全不兼容?在这种情况下,gem是作为YARV的C扩展编写的,因此它只与YARV一起工作,而不与任何其他Ruby实现一起工作,包括但不限于JRuby、Rubinius、MagLev、MRuby、IronRuby等 可悲的是:据我所知,它只使用公共RubyAPI,实际上没有使用YARV VM的任何私有内部信息,所以它也可以用便携式Ruby编写 一般来说,

我运行了
bundle安装
,令我惊讶的是,安装了Rails 4的大多数Gem都很好
byebug
不是这样,但没什么大不了的


是什么使gem与JRuby完全不兼容?

在这种情况下,gem是作为YARV的C扩展编写的,因此它只与YARV一起工作,而不与任何其他Ruby实现一起工作,包括但不限于JRuby、Rubinius、MagLev、MRuby、IronRuby等

可悲的是:据我所知,它只使用公共RubyAPI,实际上没有使用YARV VM的任何私有内部信息,所以它也可以用便携式Ruby编写

一般来说,gem只能在一个特定的Ruby实现上工作有几个原因:

  • 它使用了主机平台的某些特定功能,这些功能不是所有Ruby实现都可以使用的。例如,用Java编写的使用Java平台库的gem很可能不适用于YARV,而只适用于JRuby
  • 它访问特定Ruby实现的私有内部实现细节。我认为这是显而易见的。不太明显的是,即使在基于C的Ruby实现中也没有可移植的C API。通常被称为“RubyC扩展API”的东西实际上只是YARV展示了它的内部结构。Rubinius和JRuby都投入了大量的工作来为YARV开发仿真层,因此至少有一些C扩展可以工作,但这很难。例如:YARV的垃圾收集器非常简单,它从不移动内存中的对象。许多C扩展都依赖于此,但对于现代GC(如Rubinius或JVM)来说,这根本不是真的。YARV不允许多个Ruby线程同时运行,许多C扩展都依赖于此,但对于几乎所有其他Ruby实现来说,情况并非如此。等等……另外,这些仿真层速度很慢。真慢。对于“为了性能而用C重新编写”的gem来说,它完全有可能比JRuby或Rubinius上的纯Ruby版本运行得慢。(毕竟,在某些情况下,Rubinius已经可以与C竞争了。例如,Rubinius中的
    散列
    类是用Ruby编写的,其性能与YARV的
    散列
    类相当,后者是用C编写的。)
  • 它使用了特定实现中缺少的Ruby特性。例如,在执行方法查找的积极优化的实现中,细化被广泛批评为不可实现(或者更准确地说:细化,即当前指定的方式,使得不可能应用这些优化)。优化的设计者都碰巧是YARV开发人员,这并不重要,因为YARV无论如何都不会优化方法查找,但例如JRuby开发人员已经决定不实施优化。(10年前,他们对continuations做了同样的事情。)因此,如果gem使用了改进,那么它在JRuby上就不起作用了

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

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

可悲的是:据我所知,它只使用公共RubyAPI,实际上没有使用YARV VM的任何私有内部信息,所以它也可以用便携式Ruby编写

一般来说,gem只能在一个特定的Ruby实现上工作有几个原因:

  • 它使用了主机平台的某些特定功能,这些功能不是所有Ruby实现都可以使用的。例如,用Java编写的使用Java平台库的gem很可能不适用于YARV,而只适用于JRuby
  • 它访问特定Ruby实现的私有内部实现细节。我认为这是显而易见的。不太明显的是,即使在基于C的Ruby实现中也没有可移植的C API。通常被称为“RubyC扩展API”的东西实际上只是YARV展示了它的内部结构。Rubinius和JRuby都投入了大量的工作来为YARV开发仿真层,因此至少有一些C扩展可以工作,但这很难。例如:YARV的垃圾收集器非常简单,它从不移动内存中的对象。许多C扩展都依赖于此,但对于现代GC(如Rubinius或JVM)来说,这根本不是真的。YARV不允许多个Ruby线程同时运行,许多C扩展都依赖于此,但对于几乎所有其他Ruby实现来说,情况并非如此。等等……另外,这些仿真层速度很慢。真慢。对于“为了性能而用C重新编写”的gem来说,它完全有可能比JRuby或Rubinius上的纯Ruby版本运行得慢。(毕竟,Rubinius在某些情况下已经可以与C竞争了。例如,Rubinius中的
    散列
    类是用Ruby编写的,其性能与YARV的
    散列
    类w相当