Anche se idealmente MRI e JRuby si comporterebbero al 100% allo stesso modo in tutte le situazioni, ci sono alcune differenze minori. Alcune differenze sono dovute a bug, e quelli non sono riportati qui. Questa pagina è per le differenze che non sono bug.
Stack Trace Differences
Poiché JRuby è un linguaggio basato su JVM, potresti vedere alcune differenze nel modo in cui vengono renderizzate le tracce dello stack Ruby (“backtraces”). Di seguito è riportato un elenco parziale di tali casi:
- Il “nuovo” frame dalla costruzione di un oggetto potrebbe non essere presente a causa delle ottimizzazioni.
- Metodi di classe Core implementati in Java mostrerà un .file java e numero di riga in cui CRuby mostrerebbe solo la chiamata .linea rb due volte. Ciò non dovrebbe influire sull’output
caller
ecaller_locations
. - Potrebbero esserci più o meno frame a causa del modo in cui ricostruiamo una traccia dello stack dallo stack JVM.
- I blocchi nidificati non mostreranno il livello di nidificazione.
- I fotogrammi di livello superiore possono mostrare nomi diversi in cui CRuby mostra””.
In generale, il codice non dovrebbe fare affidamento su backtraces di eccezione che corrispondono esattamente a CRuby, ma quando c’è una differenza discutibile, apri un bug. Cerchiamo di abbinare CRuby il più vicino possibile.
Estensioni C native
JRuby non può eseguire estensioni C native. Le librerie popolari sono state generalmente portate su estensioni native Java. Inoltre, ora che FFI è diventata un’alternativa popolare all’associazione alle librerie C, il suo utilizzo evita la necessità di scrivere una grande quantità di estensioni native.
Continuazioni e fibre
JRuby non supporta continuazioni (Kernel.callcc).
Le fibre (una forma di continuazione delimitata) sono supportate su JRuby, ma ogni fibra è supportata da un thread nativo. Ciò può portare a problemi di risorse quando si tenta di utilizzare più fibre di quelle che il sistema consente ai thread in un determinato processo.
Invocare processi esterni
Su Microsoft Windows, JRuby è un po ‘ più intelligente quando si avviano processi esterni. Se il file eseguibile non è un eseguibile binario (.exe
), MRI richiede di dare anche il suffisso del file, ma JRuby gestisce senza di esso.
Ad esempio, supponiamo che tu abbia il file foo.bat
sul tuo PERCORSO e desideri eseguirlo.
system( 'foo' ) # works on JRuby, fails on MRIsystem( 'foo.bat' ) # works both in JRuby and MRI
Fork non è implementato
JRuby non implementa fork()
su nessuna piattaforma, inclusi quelli in cui fork()
è disponibile in MRI. Ciò è dovuto al fatto che la maggior parte delle JVM non può essere biforcuta in modo sicuro.
Endian nativo è Big Endian
Poiché la JVM presenta una CPU compatibile con JRuby, la endianità nativa di JRuby è Big Endian. Questo è importante per le operazioni che dipendono da quel comportamento, come String#unpack
e Array#pack
per formati come I
, i
, S
, e s
.
Precisione temporale
Poiché non è possibile ottenere usec
precisione in una JVM, Time.now.usec
non è possibile restituire valori con precisione nanoseconda. Questo non è più il caso di una piattaforma POSIX (da JRuby 9.1).
irb(main):004:0> Time.now.usec=> 815414
Su Windows una chiamata di sistema nativa non è implementata e quindi c’è il fallback di precisione JVM millisecondo.Tienilo a mente quando conti sulla precisione usec
nel tuo codice.
> Time.now.usec=> 582000
Priorità thread
NOTA: almeno a partire da JRuby 1.7.6, le priorità dei thread Ruby sono mappate alle priorità dei thread Java, quindi questa sezione non è accurata: è possibile utilizzare la stessa priorità per MRI e JRuby.
In MRI, la priorità del thread può essere impostata su qualsiasi valore in Fixnum (se i thread nativi sono abilitati) o -3..3 (se non). Il valore predefinito è 0.
In JRuby, i thread sono supportati da thread Java e la priorità varia da 1 a 10, con un valore predefinito di 5. Se si passa un valore al di fuori di questo intervallo a Thread#priority=
, la priorità verrà impostata su 1 o 10.
NOTA: che la JVM potrebbe ignorare le priorità, dipende davvero dal sistema operativo di destinazione e con Java (più vecchio) è necessario passare l’extra -XX:UseThreadPriorities
per utilizzarli.
SystemStackError
JRuby non è in grado di salvare da SystemStackError
. Se il tuo codice si basa su questo, dovresti piuttosto provare a catturare un Java::JavaLang::StackOverflowError
. Vedi questo biglietto per ulteriori informazioni.
‘proc’Argumentless
Se si fornisce proc
senza argomenti e il metodo viene passato a un blocco, Ruby finirà per catturare il blocco passato. Alcune persone scoprono questo e porta a un modello raro di proc.call
. Non sosteniamo questo comportamento. Il problema è che proc come funzione è relativamente comune ma ci costringe a deottimizzare tutti gli usi di proc come proc { #some code }
. Il lavoro consigliato è dichiarare esplicitamente il blocco usando una e commerciale def foo(&my_proc)...
. Se si desidera un comportamento analogico a proc, si consente anche Proc.new
che funzionerà esattamente come una chiamata bare proc.