Quali sono i vantaggi del bytecode rispetto al codice nativo?

Sembra che tutto ciò che puoi fare con il bytecode tu possa farlo altrettanto facilmente e molto più velocemente nel codice nativo. In teoria, potresti anche mantenere l’indipendenza dalla piattaforma e dalla lingua distribuendo programmi e librerie in bytecode, quindi compilando il codice nativo al momento dell’installazione, piuttosto che JIT.

Quindi, in generale, quando vorresti eseguire bytecode anziché nativo?

Hank Shiffman di SGI ha detto (molto tempo fa, ma è vero):

Ci sono tre vantaggi di Java che utilizzano il codice byte invece di andare al codice nativo del sistema:

  1. Portabilità : ogni tipo di computer ha il suo set di istruzioni unico. Mentre alcuni processori includono le istruzioni per i loro predecessori, è generalmente vero che un programma che gira su un tipo di computer non funzionerà su nessun altro. Aggiungi i servizi forniti dal sistema operativo, che ogni sistema descrive in modo univoco e hai un problema di compatibilità. In generale, non è ansible scrivere e compilare un programma per un tipo di sistema ed eseguirlo su un altro senza molto lavoro. Java aggira questa limitazione inserendo la sua macchina virtuale tra l’applicazione e l’ambiente reale (computer + sistema operativo). Se un’applicazione è compilata su un codice byte Java e tale codice byte viene interpretato allo stesso modo in ogni ambiente, è ansible scrivere un singolo programma che funzionerà su tutte le diverse piattaforms in cui è supportato Java. (Questa è la teoria, comunque. In pratica ci sono sempre piccole incompatibilità in agguato per il programmatore.)

  2. Sicurezza : una delle virtù di Java è la sua integrazione nel web. Carica una pagina Web che utilizza Java nel browser e il codice Java viene scaricato ed eseguito automaticamente. Ma cosa succede se il codice distrugge i file, sia attraverso la cattiveria o la sciatteria da parte del programmatore? Java impedisce alle applet scaricate di fare qualcosa di distruttivo impedendo operazioni potenzialmente pericolose. Prima di consentire al codice di eseguirlo, lo esamina per tentativi di aggirare la sicurezza. Verifica che i dati vengano utilizzati in modo coerente: il codice che manipola un elemento di dati come un intero in uno stadio e quindi tenta di utilizzarlo come puntatore in seguito verrà catturato e impedito l’esecuzione. (Il linguaggio Java non consente l’aritmetica del puntatore, quindi non è ansible scrivere codice Java per fare ciò che abbiamo appena descritto.Tuttavia, non c’è nulla che impedisca a qualcuno di scrivere codice byte distruttivo da solo usando un editor esadecimale o anche costruendo un byte Java assemblatore di codice.) Generalmente non è ansible analizzare il codice macchina di un programma prima dell’esecuzione e determinare se fa qualcosa di male. Trucchi come scrivere codice auto-modificante significano che le operazioni malvagie potrebbero non esistere nemmeno fino a dopo. Ma il codice byte Java è stato progettato per questo tipo di convalida: non ha le istruzioni che un programmatore malintenzionato userebbe per hide il proprio assalto.

  3. Dimensione : nel mondo dei microprocessori RISC è generalmente preferibile rispetto a CISC. È meglio avere un piccolo set di istruzioni e usare molte istruzioni veloci per fare un lavoro piuttosto che avere molte operazioni complesse implementate come istruzioni singole. I progetti RISC richiedono un minor numero di porte sul chip per implementare le loro istruzioni, consentendo più spazio per le condotte e altre tecniche per rendere più veloce ogni istruzione. In un interprete, tuttavia, nulla di ciò è importante. Se si desidera implementare una singola istruzione per l’istruzione switch con una lunghezza variabile in base al numero di clausole case, non c’è motivo di non farlo. In effetti, un set di istruzioni complesso è un vantaggio per un linguaggio basato sul web: significa che lo stesso programma sarà più piccolo (meno istruzioni di maggiore complessità), il che significa meno tempo per il trasferimento attraverso la nostra rete a velocità limitata.

Pertanto, quando si considera il codice byte e il nativo, considerare quali sono i compromessi tra portabilità, sicurezza, dimensione e velocità di esecuzione. Se la velocità è l’unico fattore importante, vai nativo. Se uno degli altri è più importante, vai con il bytecode.

Aggiungerò anche che il mantenimento di una serie di compilazioni OS e di architetture mirate della stessa base di codice per ogni versione può diventare molto noioso. È una grande vittoria utilizzare lo stesso bytecode Java su più piattaforms e farlo funzionare “.

Le prestazioni di qualsiasi programma miglioreranno se compilate, eseguite con il profiling e i risultati restituiti al compilatore per un secondo passaggio. I percorsi di codice che vengono effettivamente utilizzati saranno ottimizzati in modo più aggressivo, i loop verranno srotolati esattamente al giusto grado e i percorsi di istruzioni a caldo organizzati per massimizzare i colpi di I $.

Tutto bene, eppure non è quasi mai fatto perché è fastidioso fare tanti passi per build un binario.

Questo è il vantaggio di eseguire il bytecode per un po ‘di tempo prima di compilarlo nel codice nativo: le informazioni di profilazione sono automaticamente disponibili. Il risultato dopo la compilazione Just-In-Time è un codice nativo altamente ottimizzato per i dati specifici che il programma sta elaborando.

Essere in grado di eseguire il bytecode consente inoltre un’ottimizzazione nativa più aggressiva di quella che un compilatore statico potrebbe tranquillamente utilizzare. Ad esempio, se si nota che uno degli argomenti di una funzione è sempre NULL, tutta la gestione di quell’argomento può semplicemente essere omessa dal codice nativo. Ci sarà un breve controllo di validità degli argomenti nel prologo della funzione, se quell’argomento non è NULL, la VM si rimanda al bytecode e ricomincia la profilazione.

Bytecode crea un ulteriore livello di riferimento indiretto.

I vantaggi di questo livello extra di indirezione sono:

  • Indipendenza dalla piattaforma
  • È ansible creare qualsiasi numero di linguaggi di programmazione (syntax) e farli compilare allo stesso bytecode.
  • Potrebbe facilmente creare convertitori di linguaggio incrociato
  • x86, x64 e IA64 non devono più essere compilati come binari separati. È necessario installare solo la macchina virtuale appropriata.
  • Ogni SO ha semplicemente bisogno di creare una macchina virtuale e avrà il supporto per lo stesso programma.
  • La compilazione just in time consente di aggiornare un programma semplicemente sostituendo un singolo file sorgente con patch. (Molto utile per le pagine Web)

Alcuni degli svantaggi:

  • Prestazione
  • Più facile da decompilare

Tutte buone risposte, ma il mio tasto di scelta rapida è stato colpito: le prestazioni.

Se il codice da eseguire spende tutto il suo tempo chiamando le routine di libreria / sistema – operazioni sui file, operazioni di database, invio di messaggi di Windows, quindi non importa molto se è JITted, perché la maggior parte del tempo di clock è trascorso in attesa di quelle inferiori operazioni di livello da completare.

Tuttavia, se il codice contiene cose che di solito chiamiamo “algoritmi”, che devono essere veloci e che non impiegano molto tempo a chiamare le funzioni, e se sono usate abbastanza spesso per essere un problema di prestazioni, allora JIT è molto importante.

Penso che tu abbia appena risposto alla tua stessa domanda: indipendenza dalla piattaforma. Il bytecode indipendente dalla piattaforma viene prodotto e distribuito alla sua piattaforma di destinazione. Quando viene eseguito, viene rapidamente compilato nel codice nativo prima che inizi l’esecuzione o simultaneamente ( Just In Time ). La Java JVM e presumibilmente i runtime .NET operano su questo principio.

Qui: http://slashdot.org/developers/02/01/31/013247.shtml

Vai a vedere cosa hanno da dire i geek di Slashdot! Piccoli commenti datati ma molto belli!

Idealmente, avresti un bytecode portatile che compila Just In Time al codice nativo. Penso che la ragione per cui gli interpreti bytecode esistono senza JIT è dovuta principalmente al fatto pratico che la compilazione di codice nativo aggiunge complessità a una macchina virtuale. Ci vuole tempo per build, eseguire il debug e mantenere quel componente aggiuntivo. Non tutti hanno il tempo o le risorse per fare questo impegno.

Un fattore secondario è la sicurezza. È molto più semplice verificare che un interprete non si arresti in modo anomalo che garantire lo stesso per il codice nativo.

Terzo è il rendimento. Spesso può essere necessario più tempo per generare codice macchina che interpretare bytecode per piccoli pezzi di codice che vengono eseguiti una sola volta.

Portabilità e indipendenza dalla piattaforma sono probabilmente i vantaggi più importanti del bytecode rispetto al codice nativo.