I tre tipi di portabilità di Java

Java ha suscitato molto entusiasmo nella comunità di programmazione perché promette applicazioni e applet portatili . In effetti, Java fornisce tre distinti tipi di portabilità: portabilità del codice sorgente, portabilità dell'architettura della CPU e portabilità del sistema operativo / GUI. Il fatto che esistano tre tipi distinti di portabilità è fondamentale, perché solo uno di questi tipi è una minaccia per Microsoft. Ci si può aspettare che Microsoft minerà quel tipo di portabilità mentre abbraccia gli altri due, sostenendo nel contempo di supportare Java. Comprendere i tre tipi di portabilità e il modo in cui interagiscono è fondamentale per comprendere la minaccia per Microsoft e le possibili risposte di Microsoft.

Prima di entrare nei dettagli su ciascuno di questi tre tipi di portabilità, tuttavia, esaminiamo alcuni termini fondamentali.

Definizione di alcuni termini

In questo articolo vengono utilizzati i seguenti termini:

Endianismo
Endianism si riferisce all'ordine di archiviazione dei byte in una quantità multibyte in una data CPU. Ad esempio, il numero breve senza segno 256 (decimale) richiede due byte di spazio di archiviazione: 0x01 e 0x00. Questi due byte possono essere memorizzati in qualsiasi ordine: 0x01, 0x00o 0x00, 0x01. L'endianesimo determina l'ordine in cui vengono memorizzati i due byte. Per scopi pratici, l'endianismo di solito conta solo quando CPU di endianismo diverso devono condividere dati.
Giava
Java è composto da diverse tecnologie diverse impacchettate insieme: il linguaggio di programmazione Java, la Java virtual machine (JVM) e le librerie di classi associate al linguaggio. Questo articolo discute tutti questi aspetti.
Java virtual machine (JVM)

La JVM è una CPU immaginaria per la quale la maggior parte dei compilatori Java emette codice. Il supporto per questa CPU immaginaria è ciò che consente ai programmi Java di funzionare senza essere ricompilati su CPU diverse. Niente nel linguaggio di programmazione Java richiede la compilazione del codice sorgente Java nel codice per la JVM invece che nel codice oggetto nativo.

In effetti, Asymetrix e Microsoft hanno annunciato compilatori Java che emettono applicazioni Microsoft Windows native. (Vedere la sezione Risorse di questo articolo per ulteriori informazioni.)

Codice J.
Il codice J è l'output emesso dalla maggior parte dei compilatori Java nei file di classe. Il codice J può essere pensato come un codice oggetto per la macchina virtuale Java.
Portabilità
La portabilità si riferisce alla capacità di eseguire un programma su macchine diverse. L'esecuzione di un determinato programma su macchine diverse può richiedere diverse quantità di lavoro (ad esempio, nessun lavoro di sorta, ricompilazione o piccole modifiche al codice sorgente). Quando le persone si riferiscono ad applicazioni e applet Java come portatili, di solito intendono che le applicazioni e le applet vengono eseguite su diversi tipi di macchine senza modifiche (come ricompilazione o modifiche al codice sorgente).

Ora che abbiamo coperto alcuni termini essenziali, spiegheremo ciascuno dei tre tipi di portabilità di Java.

Java come linguaggio: portabilità del codice sorgente

Come linguaggio di programmazione, Java fornisce la forma più semplice e familiare di portabilità: la portabilità del codice sorgente. Un determinato programma Java dovrebbeproducono risultati identici indipendentemente dalla CPU, dal sistema operativo o dal compilatore Java sottostante. Questa idea non è nuova; linguaggi come C e C ++ hanno fornito l'opportunità per questo livello di portabilità per molti anni. Tuttavia, C e C ++ forniscono anche numerose opportunità per creare codice non portabile. A meno che i programmi scritti in C e C ++ non siano progettati per essere portabili fin dall'inizio, la capacità di spostarsi su macchine diverse è più teorica che pratica. C e C ++ lasciano dettagli indefiniti come la dimensione e l'endianismo dei tipi di dati atomici, il comportamento della matematica in virgola mobile, il valore delle variabili non inizializzate e il comportamento quando si accede alla memoria liberata.

In breve, sebbene la sintassi di C e C ++ sia ben definita, la semantica non lo è. Questa scioltezza semantica consente a un singolo blocco di codice sorgente C o C ++ di compilare programmi che danno risultati diversi se eseguiti su CPU, sistemi operativi, compilatori diversi e persino su una singola combinazione compilatore / CPU / OS, a seconda delle varie impostazioni del compilatore. (Vedere la barra laterale Sintassi e semantica per una discussione sulle differenze tra semantica e sintassi.)

Java è diverso. Java fornisce una semantica molto più rigorosa e lascia meno all'implementatore. A differenza di C e C ++, Java ha dimensioni ed endianesimo definiti per i tipi atomici, oltre a un comportamento in virgola mobile definito.

Inoltre, Java definisce più comportamenti rispetto a C e C ++. In Java, la memoria non viene liberata fino a quando non è più possibile accedervi e il linguaggio non ha variabili non inizializzate. Tutte queste caratteristiche aiutano a restringere la variazione nel comportamento di un programma Java da piattaforma a piattaforma e da implementazione a implementazione. Anche senza JVM, ci si può aspettare che i programmi scritti in linguaggio Java vengano portati (dopo la ricompilazione) su diverse CPU e sistemi operativi molto meglio dei programmi C o C ++ equivalenti.

Sfortunatamente, le funzionalità che rendono Java così portatile hanno un aspetto negativo. Java presuppone una macchina a 32 bit con byte a 8 bit e matematica a virgola mobile IEEE754. Le macchine che non si adattano a questo modello, inclusi microcontrollori a 8 bit e supercomputer Cray, non possono eseguire Java in modo efficiente. Per questo motivo, dovremmo aspettarci che C e C ++ vengano utilizzati su più piattaforme rispetto al linguaggio Java. Dovremmo anche aspettarci che i programmi Java portino più facilmente di C o C ++ tra quelle piattaforme che supportano entrambi.

Java come macchina virtuale: portabilità della CPU

La maggior parte dei compilatori produce codice oggetto che gira su una famiglia di CPU (ad esempio, la famiglia Intel x86). Anche i compilatori che producono codice oggetto per diverse famiglie di CPU (ad esempio, x86, MIPS e SPARC) producono solo codice oggetto per un tipo di CPU alla volta; se hai bisogno di codice oggetto per tre diverse famiglie di CPU, devi compilare il tuo codice sorgente tre volte.

Gli attuali compilatori Java sono diversi. Invece di produrre output per ogni diversa famiglia di CPU su cui il programma Java deve essere eseguito, gli attuali compilatori Java producono codice oggetto (chiamato codice J) per una CPU che non esiste ancora.

(Sun ha annunciato una CPU che eseguirà direttamente il codice J, ma indica che i primi campioni di chip Java non appariranno fino alla seconda metà di quest'anno; la produzione completa di tali chip inizierà l'anno prossimo. Tecnologia di base picoJavaI di Sun Microelectronics sarà al centro della linea di processori microJava di Sun, che avrà come target i computer di rete. Anche licenziatari come LG Semicon, Toshiba Corp. e Rockwell Collins Inc. prevedono di produrre chip Java basati sul core picoJavaI.)

Per ogni CPU reale su cui devono essere eseguiti i programmi Java, un interprete Java o una macchina virtuale "esegue" il codice J. Questa CPU inesistente consente l'esecuzione dello stesso codice oggetto su qualsiasi CPU per la quale esiste un interprete Java.

La produzione di output per una CPU immaginaria non è nuova con Java: i compilatori Pascal UCSD (University of California at San Diego) hanno prodotto codice P anni fa; Limbo, un nuovo linguaggio di programmazione in fase di sviluppo presso Lucent Technologies, produce codice oggetto per una CPU immaginaria; e Perl crea una rappresentazione di programma intermedia ed esegue questa rappresentazione intermedia invece di creare codice eseguibile nativo. La JVM esperta di Internet si distingue da queste altre implementazioni di CPU virtuali perché è stata progettata intenzionalmente per consentire la generazione di codice sicuro e privo di virus. Prima di Internet, non era necessario che le macchine virtuali dimostrassero che i programmi fossero sicuri e privi di virus. Questa caratteristica di sicurezza, combinata con una migliore comprensione di come eseguire rapidamente programmi per CPU immaginarie, ha portato adiffusa accettazione della JVM. Oggi, la maggior parte dei principali sistemi operativi, inclusi OS / 2, MacOS, Windows 95 / NT e Novell Netware, hanno, o dovrebbero avere, supporto integrato per i programmi J-code.

La JVM, essendo essenzialmente una CPU immaginaria, è indipendente dal linguaggio del codice sorgente. Il linguaggio Java può produrre codice J. Ma anche Ada95. In effetti, gli interpreti ospitati in codice J sono stati scritti per diversi linguaggi, tra cui BASIC, Forth, Lisp e Scheme, ed è quasi certo che le implementazioni di altri linguaggi emetteranno codice J in futuro. Una volta che il codice sorgente è stato convertito in codice J, l'interprete Java non può dire quale linguaggio di programmazione ha creato il codice J che sta eseguendo. Il risultato: portabilità tra diverse CPU.

Il vantaggio di compilare programmi (in qualsiasi lingua) in J-code è che lo stesso codice viene eseguito su diverse famiglie di CPU. Lo svantaggio è che il codice J non viene eseguito velocemente come il codice nativo. Per la maggior parte delle applicazioni, questo non avrà importanza, ma per i programmi di fascia alta più alti, quelli che richiedono fino all'ultima percentuale della CPU, il costo delle prestazioni del codice J non sarà accettabile.

Java come sistema operativo virtuale e GUI: portabilità del sistema operativo

La maggior parte dei programmi Microsoft Windows scritti in C o C ++ non vengono portati facilmente in ambienti Macintosh o Unix, anche dopo la ricompilazione. Anche se i programmatori prestano particolare attenzione ad affrontare le debolezze semantiche in C o C ++, il porting è difficile. Questa difficoltà si verifica anche quando il porting al sistema operativo non Windows avviene senza cambiare CPU. Perché la difficoltà?

Dopo aver eliminato i problemi semantici in C e C ++ ei problemi di porting della CPU, i programmatori devono ancora occuparsi del diverso sistema operativo e delle diverse chiamate API della GUI.

I programmi Windows effettuano chiamate molto diverse al sistema operativo rispetto ai programmi Macintosh e Unix. Queste chiamate sono fondamentali per scrivere programmi non banali, quindi finché questo problema di portabilità non viene risolto, il porting rimarrà difficile.

Java risolve questo problema fornendo un insieme di funzioni di libreria (contenuta nelle librerie Java in dotazione quali awt, util, e lang) che parlare di un sistema operativo immaginario e GUI immaginario. Proprio come la JVM presenta una CPU virtuale, le librerie Java presentano un OS / GUI virtuale. Ogni implementazione Java fornisce librerie che implementano questo OS / GUI virtuale. I programmi Java che utilizzano queste librerie per fornire la porta delle funzionalità OS e GUI necessarie abbastanza facilmente.

L'utilizzo di una libreria di portabilità al posto delle chiamate OS / GUI native non è un'idea nuova. Prodotti come Galaxy di Visix Software e Zinc di Protools Software forniscono questa funzionalità per C e C ++. Un altro approccio, non seguito da Java, consiste nello scegliere un singolo OS / GUI come master e fornire librerie wrapper che supportano questo OS / GUI principale su tutte le macchine su cui si desidera eseguire il port. Il problema con l'approccio OS / GUI principale è che le applicazioni portate spesso sembrano estranee sulle altre macchine. Gli utenti Macintosh, ad esempio, si sono lamentati di una versione recente di Microsoft Word per Macintosh perché sembrava e si comportava come un programma Windows, non come un programma Macintosh. Sfortunatamente, anche l'approccio adottato da Java presenta dei problemi.

Java ha fornito una funzionalità di minimo comune denominatore nelle sue librerie OS / GUI. Le funzionalità disponibili su un solo sistema operativo / GUI, come le finestre di dialogo a schede, sono state omesse. Il vantaggio di questo approccio è che la mappatura della funzionalità comune al sistema operativo / GUI nativo è abbastanza semplice e, con cura, può fornire applicazioni che funzionano come previsto sulla maggior parte dei sistemi operativi / GUI. Lo svantaggio è che sarà disponibile una funzionalità per le applicazioni in modalità nativa che non è disponibile per le applicazioni Java. A volte gli sviluppatori saranno in grado di aggirare questo problema estendendo l'AWT; altre volte non lo faranno. In quei casi in cui la funzionalità desiderata è irraggiungibile con soluzioni alternative, molto probabilmente gli sviluppatori sceglieranno di scrivere codice non portatile.

A chi importa della portabilità?

Tre componenti principali si preoccupano della portabilità: sviluppatori, utenti finali e reparti MIS.

Sviluppatori: le opportunità e le minacce sono enormi

Gli sviluppatori hanno un interesse acquisito nella creazione di software portatile. Al rialzo, il software portatile consente loro di supportare più piattaforme, il che porta a una base più ampia di potenziali clienti. Tuttavia, la stessa portabilità che consente agli sviluppatori di rivolgersi a nuovi mercati consente anche ai concorrenti di rivolgersi al proprio mercato.

In poche parole, la portabilità di Java spinge il mercato del software applicativo lontano da mercati separati basati sui vari sistemi operativi e GUI e verso un grande mercato. Nell'attuale mercato del software, ad esempio, Microsoft è una forza da non sottovalutare nei mercati del software applicativo Windows e Macintosh, ma non ha quasi alcuna presenza nei mercati OS / 2 e Unix. Questo partizionamento consente alle aziende nei mercati OS / 2 e Unix di ignorare Microsoft come concorrente. Java rende più facile per queste aziende competere nel mercato Windows, ma consente anche a Microsoft di entrare più facilmente nei mercati OS / 2 e Unix.

Utenti: i beneficiari indiretti della portabilità

Gli utenti non si preoccupano della portabilità, di per sé. Se la portabilità rende la loro vita più facile e piacevole, allora sono tutti d'accordo; se no, non lo sono. La portabilità ha alcuni effetti positivi per gli utenti, ma questi sono in qualche modo indiretti. Gli effetti positivi: