Bien qu’idéalement, l’IRM et JRuby se comporteraient à 100% de la même manière dans toutes les situations, il existe quelques différences mineures. Certaines différences sont dues à des bugs, et ceux-ci ne sont pas signalés ici. Cette page concerne les différences qui ne sont pas des bugs.
Différences de trace de pile
Étant donné que JRuby est un langage basé sur JVM, vous pouvez voir des différences dans la façon dont les traces de pile Ruby (« backtraces ») sont rendues. Une liste partielle de ces cas est ci-dessous:
- La « nouvelle » trame issue de la construction d’un objet peut ne pas être présente en raison d’optimisations.
- Les méthodes de classe de base implémentées en Java afficheront a.fichier java et numéro de ligne où CRuby montrerait simplement l’appel.ligne rb deux fois. Cela ne devrait pas affecter les sorties
caller
etcaller_locations
. - Il peut y avoir plus ou moins de trames en raison de la façon dont nous reconstruisons une trace de pile à partir de la pile JVM.
- Les blocs imbriqués n’affichent pas le niveau d’imbrication.
- Les images de niveau supérieur peuvent afficher des noms différents où CRuby affiche « ».
En général, le code ne doit pas s’appuyer sur des backtraces d’exception correspondant exactement à CRuby, mais lorsqu’il y a une différence discutable, veuillez ouvrir un bogue. Nous essayons de faire correspondre CRuby aussi étroitement que possible.
Extensions C natives
JRuby ne peut pas exécuter d’extensions C natives. Les bibliothèques populaires ont toutes généralement été portées vers des extensions natives Java. De plus, maintenant que FFI est devenu une alternative populaire à la liaison aux bibliothèques C, son utilisation évite la nécessité d’écrire un grand nombre d’extensions natives.
Continuations et fibres
JRuby ne supporte pas les continuations (Noyau.callcc).
Les fibres (une forme de continuation délimitée) sont supportées sur JRuby, mais chaque fibre est supportée par un thread natif. Cela peut entraîner des problèmes de ressources lorsque vous tentez d’utiliser plus de fibres que le système ne le permet dans un processus donné.
Appel de processus externes
Sous Microsoft Windows, JRuby est un peu plus intelligent lors du lancement de processus externes. Si le fichier exécutable n’est pas un exécutable binaire (.exe
), MRI exige que vous donniez également le suffixe du fichier, mais JRuby gère sans lui.
Par exemple, supposons que vous ayez le fichier foo.bat
sur votre CHEMIN et que vous souhaitiez l’exécuter.
system( 'foo' ) # works on JRuby, fails on MRIsystem( 'foo.bat' ) # works both in JRuby and MRI
La fourche n’est pas implémentée
JRuby n’implémente fork()
sur aucune plate-forme, y compris celles où fork()
est disponible en IRM. Cela est dû au fait que la plupart des JVM ne peuvent pas être fourchues en toute sécurité.
Endian natif est Big Endian
Étant donné que la JVM présente un processeur compatible avec JRuby, l’endian natif de JRuby est Big Endian. Cela importe pour les opérations qui dépendent de ce comportement, comme String#unpack
et Array#pack
pour des formats tels que I
, i
, S
, et s
.
Précision temporelle
Comme il n’est pas possible d’obtenir une précision usec
sous une machine virtuelle java, Time.now.usec
ne peut pas renvoyer de valeurs avec une précision nanoseconde. Ce n’est plus le cas sous une plateforme POSIX (depuis JRuby 9.1).
irb(main):004:0> Time.now.usec=> 815414
Sous Windows, un appel système natif n’est pas implémenté et il y a donc le repli de précision en millisecondes de la JVM.Gardez cela à l’esprit lorsque vous comptez sur une précision usec
dans votre code.
> Time.now.usec=> 582000
Priorité de thread
REMARQUE: au moins dès JRuby 1.7.6, les priorités de thread Ruby sont mappées aux priorités de thread Java, donc cette section n’est pas précise – vous pouvez utiliser la même priorité pour MRI et JRuby.
En IRM, la priorité des threads peut être définie sur n’importe quelle valeur dans Fixnum (si les threads natifs sont activés) ou -3..3 (sinon). La valeur par défaut est 0.
Dans JRuby, les threads sont soutenus par des threads Java, et la priorité va de 1 à 10, avec une valeur par défaut de 5. Si vous passez une valeur en dehors de cette plage à Thread#priority=
, la priorité sera définie sur 1 ou 10.
REMARQUE: que la JVM puisse ignorer les priorités, cela dépend vraiment du système d’exploitation cible et avec Java (plus ancien), vous devez passer le -XX:UseThreadPriorities
supplémentaire pour qu’ils soient utilisés.
SystemStackError
JRuby n’est pas en mesure de sauver de SystemStackError
. Si votre code s’appuie sur cela, vous devriez plutôt essayer d’attraper un Java::JavaLang::StackOverflowError
. Voir ce billet pour plus d’informations.
‘proc’ sans argument
Si vous fournissez proc
sans arguments et que la méthode se trouve avoir passé un bloc, Ruby finira par capturer le bloc passé. Certaines personnes le découvrent et cela conduit à un modèle rare de proc.call
. Nous ne soutenons pas ce comportement. Le problème est que proc en tant que fonction est relativement commun mais cela nous oblige à désoptimiser toutes les utilisations de proc comme proc { #some code }
. La solution recommandée consiste à déclarer explicitement le bloc en utilisant une esperluette def foo(&my_proc)...
. Si vous souhaitez que le comportement analogique soit proc, nous autorisons également Proc.new
qui fonctionnera exactement de la même manière qu’un appel proc nu.