- Il bytecode della JVM è il set di istruzioni compatto che la Java Virtual Machine esegue.
- Il compilatore Java produce bytecode in file
.class, non codice macchina nativo. - Lo stesso file
.classfunziona su qualsiasi piattaforma con un runtime Java, ed è questo il punto del formato. - I mod riscrivono il bytecode per modificare il gioco compilato senza mai accedere al suo codice sorgente.
Il bytecode della JVM è l'insieme di istruzioni che la Java Virtual Machine esegue. Quando si compila codice sorgente Java, il compilatore non produce codice macchina per la propria CPU. Produce bytecode, un formato compatto e portabile memorizzato nei file .class. La JVM legge tali istruzioni a runtime e le converte in codice nativo al momento dell'esecuzione.
Dove si integra Opal
Opal è un mod Fabric, e gli strumenti di modding su cui si basa svolgono il lavoro sul bytecode per te, quindi non devi toccare gli opcodes manualmente. Se desideri aggiungere comportamenti in JavaScript semplice, consulta l'introduzione alla programmazione.
Come il codice sorgente diventa bytecode
Un file .java è un testo scritto da una persona. Un file .class è l'output compilato che la JVM esegue. Il compilatore legge il tuo codice sorgente, lo verifica e scrive un file .class per ogni classe, contenente istruzioni bytecode, un pool di costanti, tabelle dei metodi e altri metadati.
Il bytecode non è legato a un processore specifico. Lo stesso file .class viene eseguito su Windows, macOS, Linux o qualsiasi sistema dotato di un runtime Java, perché la JVM è lo strato che sa come eseguire le istruzioni sulla macchina locale. Questa portabilità è il punto fondamentale del formato.
Come appaiono le istruzioni
Il bytecode è un set di istruzioni basato su uno stack. La maggior parte delle operazioni spinge valori su uno stack di operandi, li estrae e spinge un risultato. Non c'è allocazione di registri di cui preoccuparsi; il modello è deliberatamente semplice in modo che la JVM possa verificarlo ed eseguirlo rapidamente.
Alcuni esempi di opcode danno un'idea:
| Opcode | Cosa fa |
|---|---|
iload | Spinge una variabile locale int sullo stack |
iadd | Estrae due int, spinge la loro somma |
invokevirtual | Chiama un metodo di istanza |
getfield | Legge un campo di istanza |
return | Ritorna da un metodo |
Raramente leggi o scrivi questi a mano. Gli strumenti li generano e li consumano, ed è qui che entra in gioco una libreria come ASM.
Perché il bytecode è importante per le mod
Il bytecode è importante perché permette di modificare il comportamento senza il codice sorgente originale. Un mod di Minecraft quasi mai ha il codice sorgente del gioco. Ciò che ha è il gioco compilato su disco. Per aggiungere o modificare una funzionalità, un mod legge il bytecode esistente, lo riscrive e invia il risultato di nuovo alla JVM mentre le classi vengono caricate.
È così che i framework di patching inseriscono hook nei metodi che non possiedono. Trovano il punto giusto in un metodo compilato e inseriscono una chiamata al codice del mod. Lavorare a livello di bytecode significa che un mod può collegarsi al gioco anche senza vedere una riga del codice Java originale.
Dove ASM entra in gioco
ASM è una libreria Java per leggere, scrivere e trasformare bytecode. Analizza un file .class in eventi o in un albero, permette di modificare le istruzioni ed emette un file .class valido. È piccolo, veloce e lavora a stretto contatto con il formato raw, motivo per cui gli strumenti di modding di livello superiore si basano su di esso piuttosto che analizzare direttamente i file di classe.
La maggior parte dei modder non chiama mai ASM direttamente. Utilizzano un livello superiore che nasconde gli opcodes ed espone un modo più intuitivo per dire "esegui il mio codice all'inizio di questo metodo". Sotto, quel livello sta modificando il bytecode, spesso tramite ASM.
FAQ
No. Il codice macchina sono istruzioni native per una specifica CPU. Il bytecode è il set di istruzioni proprio della JVM, che la JVM traduce in codice macchina a runtime. È questo strato aggiuntivo a rendere un file .class eseguibile su qualsiasi piattaforma.
In parte. I decompilatori ricostruiscono codice Java leggibile a partire dal bytecode, e ci riescono bene con il codice ordinario. Il risultato non è sempre identico all'originale, e i commenti e alcuni nomi locali vengono persi, ma di solito è sufficiente per poter seguire il codice.
I mod solitamente non dispongono del codice sorgente. Distribuiscono il gioco compilato. Riscrivere il bytecode permette a un mod di modificare il comportamento senza toccare, o anche avere, i file Java originali.
Di solito no. I framework di modding e gli strati di scripting gestiscono il lavoro relativo al bytecode per te. Conoscere il suo funzionamento aiuta quando si debugga una patch complessa o si creano strumenti.