Java SE 7 rappresenta un importante momento evolutivo per la piattaforma Java, sia dal punto di vista tecnico, sia da quello politico-organizzativo. Nei diversi articoli di questa serie analizzeremo mese dopo mese la nascita del linguaggio Java, i suoi sviluppi nelle varie versioni, le novità e le caratteristiche della recente versione 7, e anche quello che si vede all’orizzonte per la futura versione 8. In questo primo articolo proponiamo una panoramica del corso degli eventi che hanno portato alla nascita di Java: conoscere la propria storia è fondamentale per capire da dove siamo venuti e, forse, dove stiamo andando.
Introduzione
L’importanza della storia? Incalcolabile. Non conoscere la storia, anche la propria storia, è come rimanere bambini a vita. “Ignorare che cosa sia accaduto prima della nostra nascita significa restare sempre bambini” [1].
Possiamo applicare questo alto concetto anche al nostro mondo fatto di programmazione e sviluppo: non sapere che cosa sia accaduto prima della versione Java 1.0 (e anche dopo…) equivale a rimanere programmatori junior per sempre. Per approfondire la sua competenza, uno sviluppatore Java deve anche collegare le sue conoscenze tecniche alle versioni precedenti del linguaggio e può farlo attraverso la memoria di Internet. Se non si studia, metodicamente, la via percorsa dagli architetti e sviluppatori Java o almeno dalla piattaforma JDK, si rischia di perdere il significato fondamentale di alcuni passaggi e quindi anche il loro effetto sull’attuale panorama dei linguaggi di programmazione.
Ai fini di comprendere lo sviluppo, i punti fermi, i ripensamenti e anche la possibile evoluzione del linguaggio Java, nei prossimi numeri ci concentreremo sulle passate versioni di Java e, soprattutto, sulle caratteristiche della attuale versione Java 7. Ma iniziamo questa serie di articoli con un racconto della preistoria del linguaggio quando Java non si chiamava neanche Java e la ormai scomparsa Sun Microsystems era scossa da una certa inquietudine e frustrazione generata dalla difficoltà di utilizzare il linguaggio C e C++ per la programmazione soprattutto di dispositivi elettronici “intelligenti”.
Sebbene Java sia conosciuto ai molti a partire dal 1996, quando iniziò a circolare la versione 1.0, il progetto iniziale partì tra il 1990-91, e conobbe periodi di difficoltà e grandi ripensamenti fino all’esplosione di Internet, che finì per catapultare la piattaforma Java alla ribalta della programmazione OO.
Nel prossimo articolo, proseguiremo con la presentazione ragionata delle varie versioni del linguaggio Java che si sono via via succedute, non esenti da repentini cambiamenti di strategia, fino a giungere alla versione Java SE 8, il cui rilascio è stato fissato per l’estate del 2013. Gli articoli centrali della serie entreranno nel dettaglio delle feature introdotte a partire dalla versione Java SE 7.
Agli albori c’era la “quercia”
Oak (in italiano “quercia”) è il nome del linguaggio di programmazione che ha dato il via a Java, linguaggio di cui James Gosling è considerato il “padre”. È risultato di un progetto interno, il famoso Green Project, in quella che fu Sun Microsystem (chi lo avrebbe mai immaginato che un giorno avremmo parlato della “mitica” Sun Microsystem come di un’azienda estinta?). Il nome di questa versione embrionale di Java fu dovuto a un albero di quercia, “oak” appunto, situato fuori all’ufficio su Sand Hill Road, Menlo Park, California, dove una elite di 14 professionisti della Sun Microsystem si riunì nell’aprile 1991 per ideare il linguaggio che avrebbe dovuto rimpiazzare il C++.
Figura 1 – Una immagine di James Gosling, considerato il “padre” di Java.
Il tutto ebbe inizio nel lontano dicembre 1990 quando importanti ingegneri della Sun Microsystem, tra cui Patrick Naughton, erano sempre più frustrati per via dell’utilizzo del linguaggio C++ e del suo predecessore C, per la programmazione di dispostivi elettronici intelligenti. Per evitare che Naughton lasciasse l’azienda (aveva già instaurato trattative con la NeXT), nel gennaio del 1991 gli fu offerto di lavorare a un nuovo progetto, lo Stealth Project, nome deciso da McNealy, presidente della Sun Microsystem. In gergo aziendale, i progetti “stealth” sono quelli creati dalle aziende in segreto per evitare la “fuoruscita” di informazioni sullo stato, mission, membri, etc. del progetto.
Da “stealth” a “green”
James Gosling e Mike Sheridan si unirono a Naughton poche settimane dopo,il 1 febbraio 1991, e il progetto fu rinominato in un meno “spionistico” Green Project [3]. Secondo Gosling [11] la mission di questo progetto doveva essere di pensare, comprendere e quindi indirizzare e sfruttare il prossimo trend tecnologico (the “next wave”). Secondo gli studi iniziali del team, l’evoluzione tecnologica avrebbe dovuto investire la logica di gestione dei dispositivi di largo consumo. Naughton, Gosling e Sheridan, membri dell’original Green Team, si organizzarono come segue:
- Gosling si dedicò al linguaggio di programmazione; in particolare, aveva l’incarico di coniare nuove idee e sperimentare possibili soluzioni;
- Naughton si occupava della parte grafica;
- Sheridan aveva la responsabilità di pianificare e gestire gli sviluppi business.
Inizialmente, Gosling considerò l’utilizzo del C++; tuttavia questa idea fu respinta senza indugio per via di una serie di considerazioni, tra cui le più importanti erano la necessità di disporre di un linguaggio capace di funzionare in ambienti embedded, caratterizzati da un’endemica scarsità di risorse, senza dover richiedere particolari sofismi agli sviluppatori; la mancanza di un dispositivo automatico di allocazione/deallocazione della memoria (Garbage Collector), problema considerato cardine e generatore di bug nei programmi scritti in C; la mancanza di abilità native di networking, threading, e soprattutto di trasporto su diverse piattaforme. Scartata l’opzione C++, il tentativo successivo consistette nel cercare di modificare il C++, rimuovendo alcune parti e introducendone altre. La versione che ne doveva nascere fu ribattezzata C++ — ++” [4], dove “++” indicava le nuove feature da aggiungere, mentre il “–” rappresentava quelle da rimuovere.
Anche questo tentativo fallì dopo qualche iterazione, cosicche’, nel Giugno 1991, Gosling iniziò a lavorare a un nuovo linguaggio: Oak, con l’obiettivo di sfruttare il meglio dei linguaggi OO esistenti (Cedar-Mesa, SmallTalk, Objective C, C++ ed Eiffel). In particolare, gli sforzi si concentrarono nello sviluppo dell’interprete Oak, scritto in C.
Nell’agosto del 1991, il Green Team tenne una prima dimostrazione ai co-fondatori di Sun Microsystem, Scott McNealy e Bill Joy, riuscendo a mostrare alcune idee base e feature della GUI. Si trattava della prima applicazione funzionante (o quasi) scritta in Oak.
Tabella 1 – I membri del Green Team, in ordine alfabetico.
L’estate del 1992 fu caratterizzata da uno sviluppo forsennato. Naughton dichiarò [15] che si trattò di “massive amounts of hacking on Oak, the Green OS, the UI, and the hardware” che permise al team di mettere insieme diverse componenti della nuova piattaforma, incluso il Green Operating System, il linguaggio Oak, varie librerie e l’hardware. Il primo tangibile risultato fu dimostrato il 3 settembre 1992 con la costruzione di un PDA (Personal Digital Assitant) chiamato star7 o *7, basato su SPARC, il quale disponeva di un’interfaccia grafica e di un agente intelligente denominato Duke, ideato da Joe Palrang, con l’incaricato di assistere l’utente nell’utilizzo del dispositivo.
Figura 2 – Il membri del team Java al barbeque organizzato da Gosling [11] per celebrare il quinto anno dalla creazione della prima versione funzionante di Oak. Da sinistra a destra e dall’alto verso il basso: Al Frazier, Joe Palrang, Mike Sheridan, Ed Frank, Don Jackson, Faye Baxter, Patrick Naughton, Chris Warth, James Gosling, Bob Weisblatt, David Lavallee e Jon Payne.
Nuove direzioni: TV e Internet
Qualche tempo dopo, arrivò il primo cambio di direzione di Oak (e non sarà l’unico!): la Sun Microsystem decise di crare una “spin-off” company denominata FirstPerson dove confluirono diversi dipendenti della NeXT, con l’obiettivo di conquistare, attraverso la piattaforma Oak, il mercato della TV interattiva. Quindi l’obiettivo primario non era più la logica di controllo degli elettrodomestici di largo consumo, ma la TV interattiva via cavo. Questa nuova strategia fu largamente influenzata dalla decisione di Time Warner di avviare una serie di sperimentazioni di TV interattiva via cavo.
Un evento importante che indubbiamente segnò la storia di Java, e che ha cambiato il nostro stile di vita, fu il rilascio nel 1993 del primo browser internet grafico: NCSA Mosaic 1.0 (aprile 1993). La disponibilità di un browser Internet grafico relativamente user-friendly, che nascondeva la sequenza di oscuri comandi Unix, è da molti considerata tra le ragioni alla base dell’esplosione di Internet negli anni seguenti. Ma è anche uno degli eventi che favorì il grande successo di Java.
Nel giugno del 1994, un fulmine si abbattè sulla quercia. La cronaca riporta che ci fu una lunga serie di trattative e negoziazioni, di positivi test tecnici che portarono al riconoscimento della superiotà tecnica della piattaforma Oak. Ciò nonostante, per lo sviluppo della propria piattaforma di TV interattiva via cavo, la Time Warner optò per l’utilizzo della piattaforma proposta dalla SGI, Silicon Graphics Inc, anche denominata Silicon Graphics Computer System SGCS (l’azienda produttrice di soluzioni hardware e software ad alta prestazione che inizialmente si rivolgeva primariamente al mercato della grafica 3D).
A questo punto veniva a mancare il primo importante cliente per la piattaforma Oak; pertanto, Naughton diede luogo a una lunghissima serie di “perigrinaggi” in giro per il mondo per cercare clienti interessati alla piattaforma Oak. A questo grande dispiego di energie, ahime’, non corrisposero significativi risultati, almeno in termini commerciali. Ecco quindi che si rendeva necessaria l’eleborazione di una nuova strategia. Nel giugno e luglio 1994, dopo tre giorni di brainstorming, a cui parteciparono John Gage, direttore del Science for Sun Microsystem, Gosling, Joy, Naughton, Wayne Rosing, e Eric Schmidt, il team decise si cambiare nuovamente gli obiettivi decidendo di muovere verso una piattaforma per il World Wide Web. Ritennnero che grazie all’avvento dei browser web grafici, come Mosaic, Internet era ormai nel suo cammino verso il grande successo.
E dalla quercia venne il caffè
Nel settembre del 1994, Jonathan Payne e Naughton scrissero (in un weekend di hacking ispirato) un prototipo di browser denominato WebRunner (dal nome del film Blade Runner), ribattezzato in seguito in HotJava.
Nell’autunno del 1994 Arthur von Hoff implementò il primo compilatore Java scritto interamente in Java, sostituendo la versione precedente scritta da Gosling in C. Van Hoff era entrato nel team nel settembre del 1993 con l’obiettivo di sviluppare software per la TV interattiva, finendo invece per dedicare la quasi totalità del suo tempo al disegno di Oak. Nello stesso periodo, Sami Shaio iniziò a lavorare alla libreria GUI Abstract Window Toolkit. (AWT). A questo punto l’intera piattaforma, a parte il solo interprete, era scritta in Java.
Oak fu poi ribattezzato in Java nel 1994: il nuovo nome fu ideato dalla responsabile marketing del “prodotto”, Kim Polese [10]. A seguito degli esiti di una ricerca sui marchi di fabbrica registrati, si apprese che il nome Oak era già stato utilizzato da un’altra azienda IT: la Oak Technology.
La versione Java 1.0a fu resa disponibile per il download nel 1994. La prima release pubblica di Java fu la 1.0a2 accompagnata dal browser HotJava il 23 maggio 1995 come annunciato da Gage nella conferenza SunWorld. Questo annuncio fu accompagnato da un comunicato a sorpresa da parte di Marc Andreessen, vice presidente esecutivo di Netscape Communications Corporation, il quale dichiarò che Netscape avrebbe incluso Java.
Nel settembre del 1995 Sun Microsystem sponsorizzò quella che può essere considerata la prima conferenza sullo sviluppo in Java a New York City. Nel dicembre del 1995 importanti gruppi come Borland, Mitsubishi Electronics, Sybase e Symatec, ai quali più tardi si aggiunse anche Adobe, seguirono l’esempio della Toshiba, decidendo di voler supportare Java. Il 9 gennaio 1996, la Sun Microsystem decise di formare il gruppo JavaSoft per continuare lo sviluppo della tecnologia Java. Il resto è storia, ed è argomento del prossimo articolo, in cui vedremo le caratteristiche delle varie versioni della piattaforma.
Tabella 2 – La cronologia degli eventi principali che portarono alla nascita di Java.
Lasciando quindi qui il raccondo degli eventi, passiamo ora a una serie di riflessioni tecniche inerenti due aspetti principali del rapporto tra Oak e Java: le differenze e le continuità. Per i più interessati, le specifiche Oak [7] sono disponibili nell’allegato scaricabile dal menu più in alto a destra.
Primo aspetto: differenze tra Oak e Java
Visti gli eventi della “preistoria” di Java, prendiamo ora in considerazione gli aspetti tecnici inerenti il linguaggio Oak e la sua eredità nella piattaforma Java. Sebbene Oak sia stata la versione embrionale di Java, infatti, tra i due ci sono comunque delle importanti differenze, che possono essere raggruppate in tre principali categorie:
- feature progettate e mai implementate;
- importanti decisioni iniziali, rettificate con l’evoluzione del linguaggio;
- soluzioni rimosse.
Nei prossimi paragrafi analizziamo proprio queste tre categorie di differenze tra Oak e Java.
Feature delle specifiche originali Oak poi non implementate
Una serie di caratteristiche inizialmente presenti in Oak non furono poi manenute nella prima versione di Java. Alcune di queste caratteristiche sono ricomparse solo in versioni molto più recenti della piattaforma.
Unsigned primitive types
I tipi primitivi senza segno erano inizialmente stati presi in considerazione. Molti linguaggi di programmazione come il C ed il C++ offrono diversi tipi interi, di diverse dimensioni con e senza segno, come per esempio, unsigned/signed char, unsigned/signed short, unsigned/signed int e unsigned/signed long. Questa feature era inizialmente presente nelle specifiche iniziali di Oak, ma venne successivamente abbandonata probabilmente per contenere la complessità del linguaggio [6]. Le specifiche iniziali includevano la seguente affermazione “The four integer types of widths of 8, 16, 32 and 64 bits, are signed unless prefixed by the unsigned modifier”, sebbene la keyword unsigned non sia mai stata implementata.
enum
I tipi enumerati non furono implementati nella versione iniziale di Java: questo costrutto è stato introdotto solo con Java 5.0.
Assert
Gli assert sono un costrutto introdotto solo con la versione Java 1.4
clone
Le specifiche originali di Oak includevano la parola chiave clone che poi però non è mai stata implementata
Importanti decisioni iniziali successivamente rettificate
Ci sono alcune “prese di posizione” che avevano inizialmente caratterizzato Oak, ma che poi sono state riviste in una qualche fase di implementazione di Java, a causa di ripensamenti motivati.
Memory allocation for integer types
Secondo le specifiche iniziali di Oak, le variabili di tipo intero non avevano conseguenza sulla relativa allocazione di memoria, ma si limitavano a specificarne le proprietà e il range. Per esempio, lo spazio di memoria previsto per valori byte e short era comunque di 4 byte. Pertanto, gli effetti della dichiarazione del tipo erano relativi esclusivamente alla grammatica, all’insieme dei valori ammissibile, etc. Quesa soluzione è stata rivista con la versione Java 1.4
Abstract method
La definizione dei metodi astratti seguiva il formato previsto da C++, del tipo:
public interface Eater { void eat(Food aFood) = 0; }
Quest soluzione è stata rivista successivamente.
Livello di accesso di tipo package
Oak non prevedeva un livello di accesso di tipo package. Le classi senza livello di accesso erano considerate private (di default). Questa decisione fu poi rivista in Java 1.0. Tuttavia una certa confusione circa i livelli di accesso (access modifier) perdurò per qualche tempo. Infatti, la versione Java 1.0 prevedeva ben 5 livelli di acesso: private, private protected, protected, default, public. Vista la confusione, questa decisione fu rivisitata già dalla versione Java 1.1 optando per i 4 livelli di accesso che conosciamo oggi.
Soluzioni tecniche rimosse
Ci sono infine differenze consistenti nella rimozione in Java di certe soluzioni già adottate in Oak.
Unchecked exception
Tuttle le eccezioni previste da Oak erano di tipo unchecked, e quindi non era prevista la keyword throws. Questa soluzione fu considerata pericolosa in quanto finiva per generare codice fragile [12] e pertanto si decise di optare per la strategia di Modula 3: la quasi totalità delle eccezioni divenne checked.
protected/unproctect
Oak prevedeva il costrutto protect che permetteva di scrivere codice “protetto”. Tale codice, quindi, non poteva essere interrotto da eccezioni asincrone, quali per esempio l’eccezione derivata da un OutOfMemory, oppure dalla pressione della combinazione CTRL + C per terminare l’esecuzione del programma. In particolare, la parte di codice da salvaguardare da eccezioni asincrone doveva essere introdotto dalla corrispondente parola chiave:
protect { /* Sezione di codice protetto */ }
I costrutti protected e unprotected non furono poi integrati in Java.
DbC: Design by Contract
Oak includeva un supporto essenziale al DbC (Design by Contract, disegno per contratto) ripreso da Eiffel. In particolare, era possibile avere delle variabili al livello di classe, vincolate da particolari condizioni che dovevano essere valide all’entrata e all’uscita di ogni metodo public e protected della classe. Anche i metodi potevano avere proprie pre- e post-condizioni, che potevano essere ereditate ma non ridefinite nelle sottoclassi. Secondo quanto scritto da Gosling [11], egli ne implementò una versione iniziale per diverse di queste feature, tuttavia dovette poi rimuoverle perche’ non aveva tempo per implementarle in toto e quindi optò per rimuoverle al fine di concludere e consegnare in tempo per un’importante deadline.
goto
Oak includeva il fastidiosissimo costrutto goto. Da notare che, sebbene in Java goto sia rimasta una parola riservata, il relativo costrutto non è poi mai stato implementato.
const
Questa parola chiave non è mai stata migrata in Java, favorendo l’uso di final.
Altre differenze minori
A parte queste differenze macroscopiche, ne esistevano altre per così dire minori. Per esempio, in Oak era possibile inserire commenti online tipo JavaDoc introdotti dalla sequenza //*. Si poteva poi eseguire il post-incremento di stringhe. Sì, avete capito bene… sipoteva avere qualcosa del genere:
String text = new String(); text = "counter "; text++
E, infine, era possibile dichiarare array nel seguente modo:
int values[20]; values[3] = 3;
Secondo aspetto: le continuità tra Oak e Java
Sebbene diversi elementi del linguaggio Java siano cambiati e si siano evoluti fino ad arrivare alle versioni odierne che tutti conosciamo, le stragrande maggioranza delle caratteristiche base che hanno conferito a Java la sua enorme popolarità sono rimaste invariate. Tra le più importanti probabilmente è il caso di menzionare quelle che riportiamo nei seguenti paragrafi.
Java RunTime Platform
La Java RunTime platform (piattaforma di esecuzione Java) rappresenta l’architettura che ha fornito la soluzione al famosissimo (e, come spesso accade, inflazionatissimo) slogan coniato in casa Sun Microsystem per illustrare le capacità cross-platform di Java “WORA: Write Once, Run Everywhere“. Chi non lo ricorda?
Linguaggi compilati vs interpretati
Prima dell’introduzione di Java, la grande maggioranza dei linguaggi di programmazione esistenti potevano essere divisi, dal punto di vista del tipo di esecuzione, nelle due principali categorie: compilati e interpretati.
Al primo gruppo appartenevano linguaggi (come per esempio COBOL, PL/I, C e C++) i quali venivano trasformati, attraverso diverse fasi, direttamente nel linguaggio assembler specifico per la determinata architettura fisica e il peculiare sistema operativo su cui dovevano funzionare. Quindi la compilazione e l’esecuzione avvengono in due fasi ben distinte. L’alternativa consisteva nell’eseguire la compilazione direttamente a tempo di esecuzione (tecnicamente in questo caso le singole istruzioni sono eseguite subito dopo il parsing). Per questo, i linguaggi appartenenti a tale seconda tipologia, venivano definiti interpretati: è il caso di SmallTalk e dei vari linguaggi di scripting come Perl e JavaScript. Entrambi gli approcci presentavano alcuni vantaggi associati a una serie di importanti inconvenienti.
Per quanto concerne i linguaggi compilati, il problema principale risultava la portabilità. Nel caso dei linguaggi C e C++, per esempio, questa caratteristica poteva essere approssimata attraverso la gestione di diversi build, di lunghe sequenze di #ifdef presenti nei file include, l’utilizzo attento dei tipi base e così via. Ciò nonostante, si trattava comunque di espedienti, e la vera portabilità spesso si traduceva nel gestire diverse versioni del codice sorgente. Inoltre, i vari programmi compilati non riuscivano a seguire le evoluzioni architetturali hardware e dei sistemi operativi diventando presto obsoleti e/o inutilizzabili. Nel caso invece dei linguaggi interpretati, a fronte di una migliore pseudo-portabilità si avevano altri problemi, come scarse performance e spesso la necessità di distribuire in qualche forma il codice sorgente.
La soluzione Oak e Java: una CPU virtuale
Gli ingegneri di Oak prima, e Java poi, decisero di utilizzare un altro approccio: adottare come piattaforma di esecuzione una CPU virtuale implementata via software. Si tratta di un’ottima strategia, seguita molto più tardi anche in casa Microsoft con la piattaforma .Net, che ha permesso alla Sun Microsystem di produrre il primo linguaggio commerciale quasi completamente slegato da uno specifico sistema operativo e da una particolare architettura hardware. Ad onore del vero, l’idea originale della macchina virtuale non è scaturita presso la Sun Microsystem: soluzioni del genere erano largamente diffuse da decenni in ambito accademico e probabilmente la vera origine di questa strategia può essere fatta risalire allo UCSD Pascal [8], ideato presso la University of California, San Diego (da cui UCSD), rilasciato nel 1978.
Con questo approccio, il codice prodotto dal compilatore Java, definito bytecode, è a tutti gli effetti il codice macchina di una CPU virtuale, denominata JVM (Java Virtual Machine). Poiche’ si tratta di una macchina virtuale, il bytecode deve poi essere trasformato nuovamente nel linguaggio macchina delle specifiche architetture. In questo modo il medesimo bytecode è in grado di funzionare per tutte le architetture hardware e sistemi operativi che dispongono di una propria versione della JVM e non soffre di problemi legati all’evoluzione hardware. Inoltre, il problema delle performance è stato largamente risolto sia perche’ non è necessario interpretare un linguagio ad alto livello, bensì una versione molto vicina al linguaggio macchina, sia attreverso l’ausilio di tecniche di “compilazione solo al momento opportuno” (just-in-time comp ilation – JIT) atte ad acelerare le performance a tempo di esecuzione eseguendo ottimizzazioni sul bytecode ed eseguendo la compilazione in anticipo rispetto alla richiesta. Tutte le JVM includono da tempo tecniche JIT. Infine, poiche’ la JVM è una macchina virtuale in grado di far funzionare il bytecode ma non se’ stessa, la piattaforma Java richiede anche un ambiente a tempo di esecuzione (runtime environment) in cui far funzionare la JVM è il Java Runtime Environment (JRE).
Linguaggio Object Oriented meno complesso
Con Java siamo in presenza di un linguaggio OO, molto simile al C++, ma decisamente più ad alto livello e quindi meno complicato. Diversi aspetti concorrono a rendere Java un linguaggio OO decisamente meno complesso rispetto al C++ a partire dalla gestione automatica dell’allocazione/deallocazione della memoria. In particolare, la JVM si occupa di allocare la memoria necessaria e poi il Garbage Collector (thread daemon della JVM) si occupa ri rimuovere la memoria occupata da oggetti non più referenziati. Questa strategia, ripresa da linguaggi quali LISP e SmallTalk, non solo ha drasticamente ridotto la quantità di codice a carico degli sviluppatori (basti pensare alle numerose parti di un sistema mediamente complesso in cui è necessario allocare e deallocare, malloc/dealloc, la memoria) ma ha anche reso il linguaggio intrinsecamente più robusto: i classici problemi di sistemi complessi scritti in C/C++, se non di ottima qualità, erano relativi a memory leak, a puntatori che andavano a leggere e/o scrivere oltre la propria area di competenza, e così via.
Garbage collection e puntatori
Come scritto da Jame Gosling [12]: “[Garbage Collection] acquired a bad reputation because it tended to take more time than was necessary. Garbage collection gained the reputation of being used by lazy programmers who didn’t want to call malloc and free. But in actual fact, there are a lot of other ways to justify it. And to my mind, one of the ways that works well when you’re talking to some hard-nosed engineer is that it helps make systems more reliable. You don’t have memory leaks or dangling pointers, and you cut your software maintenance budget in half by not having to chase them”. In Java non è possibile manipolare direttamente i puntatori: ma affermare drasticamente che in Java non ci siano puntatori è errato; ogni riferimento a un oggetto è in realtà un reference in memoria, ossia un puntatore. È invece corretto dire che questi non possono essere manipolati: è stato deciso di non includere l’artimetica dei puntatori. Altre caratteristiche che rendevano Java un linguaggio meno complesso erano il supporto nativo alla programmazione multithreading (poi correttamente rivisto), delle librerie atte a semplificare il networking, e la particolare cura della sicurezza.
La questione della sicurezza
C’è un aspetto a cui hanno giustamente conferito particolare importanzagli ingegneri che hanno pensato Oak e che lo hanno fatto evolvere in Java: la sicurezza. Si tratta di una scelta assolutamente oculata che ha concorso alla sua grande diffusione. Chiaramente, ciò non esime i programmatori dall’implementare/integrare sistemi di autenticazione e autorizzazione ma è importante contare su una piattofarma di base con un importante supporto alla sicurezza. La sicurezza, in Java, è basata su tre componenti principali: il bytecode verifier, il class loader, il security manager che, insieme, vanno a formare la cosiddetta sandbox, ossia il recinto pieno di sabbia dove è possibile giocare in tutta sicurezza.
Bytecode Verifier
Il bytecode verifier è un componente che verfica il bytecode. In particolare, esegue tutta una serie di controlli per verificare che il bytecode non sia stato artificialmente alterato, che abbia il corretto formato, che non esegua overflow o underflow, che le variabili siano accedute secondo il livello di accesso dichiarato, e così via.
Class Loader
Il class loader è esso stesso un punto importante nella sicurezza. Le JVM utilizzano diversi caricatori di classi: tra questi ve ne è uno definito primordial (primordiale), spesso scritto in C, che si occupa sia di eseguire il bootstrap della stessa JVM, sia di interagire con l’ambiente di esecuzione. I class loader svolgono essenzialmente due funzioni: si occupano di reperire il bytecode delle classi richieste dalla JVM, e di gestire i namespace (spazi dei nomi). Questi sono insiemi di nomi di classi univoci, associati alle relative istanze. Poiche’ la JVM utilizza diversi class loader, è importante che i diversi namespaces creati dai vari class loader siano correttamente messi in relazione tra loro. Problemi con la gestione dello spazio dei nomi possono portare a una serie di gravi falle nel sistema di sicurezza.
Security Manager
Il security manager è il gestore della sicurezza che esegue una serie di controlli a runtime su metodi considerati pericolosi. Il codice della libreria Java consulta il security manager ogni qualvolta abbia necessità di eseguire operazioni potenzialmenti pericolose. Il security manager ha l’autorità di porre il veto sulla relativa esecuzione generando opportune SecurityException.
Internet e il web
Sebbene all’inizio Oak fosse stato pensato per una tipologia di dispositivi diversa, e avesse avuto la prospettiva concreta di essere alla base di un sistema di televisione via cavo interattiva, i suoi ideatori seppero riorientare il progetto in direzione dell’emergente diffusione di Internet successivamente alla nascita del World Wide Web. Il grande successo di Java, come visto in precedenza, arrivò proprio grazie all’enorme espansione di Internet e al riposizionamento di Java proprio come piattaforma di supporto al Web: molte persone asseriscono che, se è vero che Java deve la sua grande popolarità a Internet, è anche vero che il web ha subito un’ulteriore accelerazione proprio grazie alla disponibilità della piattaforma Java. In particolare, con Java è possibile sia creare tradizionali applicazioni stand-alone, sia programmi da scaricare (bytecode) da pagine web che girano sul browser utente (attraverso apposita JVM).
Applet
Il successo, almeno fino a un certo punto, delle famose applet Java ne è stato la dimostrazione: e per realizzare delle applet era sufficiente estendere una delle due classi java.applet.Applet o javax.swing.JApplet, a seconda se si voleva o meno il supporto della libreria grafica Swing. L’architettura cross-platform di Java favorì la grande popolarità di Java, ma fu importante anche riuscire a rimuovere le apprensioni relative alla necessità di scaricare codice eseguibile da Internet per farlo girare nei propri PC; in questo giocò un ruolo chiave l’esteso supporto alla sicurezza: le Applet Java standard sono untrusted e quindi sono eseguite dalla JVM nella sandbox il che, di fatto, impedisce ogni accesso a dati locali come il file system o anche il solo clipboard. Da considerare inoltre che l’idea delle Applet risolveva alla radice un problema annoso, a quel tempo: la distribuzione del software. Il problema spariva in toto quanto i client scaricavano le versioni aggiornate non appena disponibili (da tener presente che i browser mantenevano nella propria cache le applet scaricate, quindi il download vero e proprio accadeva solo alla presenza di nuove versioni).
L’iniziale enfasi delle Java Applet, tuttavia, è andata scemando con il tempo, sia perche’ Java si è dimostrata una tecnologia decisamente superiore per lo sviluppo lato server, sia per qualche mossa non particolarmente strategica da parte di Sun Microsystem. Molti credono che la popolarità delle Applet Java fu drasticamente ridotta anche per via della causa legale contro Microsoft che Sun Microsystem intentò nel 1997 e vinse: Microsoft era rea di aver aggiornato la JVM con un insieme di feature proprietarie (si parlava di 50 nuovi metodi e 50 campi). Con il senno del poi, è risultato chiaro che si è trattato del classico caso di vincere una battaglia ma di perdere la guerra. Infatti, la Sun Microsystem vinse la causa, ottenne una lauta ricompensa, ma causò anche le ritorsioni di Microsoft che si rifiutò di includere gli aggiornamenti della JVM in Internet Explorer, contribuendo in maniera cruciale alla perdita di interesse per le Applet Java [16].
Le ragioni di un successo
Come è lecito attendersi, grandi successi, come lo è stato indubbiamente quello di Java, possono essere spiegati attraverso una moltitudine di aspetti. Vi è sicuramente l’aspetto tecnico, ma anche quelli commerciale e politico hanno rivestito il loro ruolo.
Motivazioni tecniche
Per quanto riguarda la dimensione tecnica, il sucesso di Java è indubbiamente dovuto alle caratteristiche del linguaggio, presentate nei paragrafi precedenti: molte di queste erano già presenti in Oak, e molte sono sopravvissute nelle diverse versioni di Java succedutesi in più di tre lustri. Inoltre, citando James Gosling, “Java è una piattaforma pratica e non un lavoro teorico da PhD: non introduce idee rivoluzionarie ma fonda le proprie radici sulle tecnologie esistenti. In particolare, incorpora strategie risultate vincenti nei linguaggi esistenti, e risolve una serie di difficoltà riconosciute ai linguaggi esistenti. Java, inoltre è un linguaggio di facile comprensione, flessibile, divertente, deterministico e non intimidatorio” [12].
Arthur von Hoff, ha asserito che Java “è una grande tecnologia che si è sviluppata nel periodo giusto. Il successo di Java è stato sicuramente alimentato da due fattori fondamentali. Il primo è l’avvento di Internet e il secondo è dovuto al fatto che i programmatori C++ hanno cominciato a rendersi sempre più conto che C++ era troppo complicato e che avevano bisogno di qualcosa di più semplice” [13].
Motivazioni “sociali”
GIà nella frase di von Hoff appena citata, si fa menzione al fatto che Java si è sviluppato da Oak “nel periodo giusto” in cui si è verificato l’avvento su scala planetaria di Internet e dei suoi servizi. La diffusione nell’uso quotidiano e lavorativo del WWW ha certo rappresentato un “ecosistema” in cui la nuova creatura ha potuto ricavarsi un’importante “nicchia ecologica” in cui svilupparsi e crescere. Senza i servizi basati su Internet, la potenza e la versatilità di Java, esemplificate in particolare nel suo pervasivo utilizzo lato server, avrebbero fatto sicuramente più fatica a raggiungere il livello di adozione odierno.
Motivazioni “politiche” e “commerciali”
Occorre anzitutto partire dal fatto che la visione della Sun Micorsystem alla metà degli anni Novanta era in netta contrapposizione rispetto alle strategie, considerate da alcuni monopolistiche, della Microsoft. La piattaforma Java finì, giocoforza, per sollecitare e porre una seria minaccia al mondo Microsoft. Questo era ben evidente a uno “spaventato” Bill Gates che si espresse con la famosa frase “[Java] scares the hell out of me”. La piattaforma Java, congiuntamente a Unix, divenne ben presto un polo ben riconoscibile intorno al quale si potevano coalizzare le forze favorevoli all’Open Source. Si trattava dell’ennesima lotta tra David e Golia [14], favorita peraltro dalla grande mossa di rendere disponibili in Internet i sorgenti di Java e di molti dei suoi componenti.
Ultimo elemento da considerare fu l’intensa e ben studiata attività di marketing condotta dalla Sun Microsystem e, in particolare, la grande enfasi posta sul fatto che Java era la piattaforma ideale per lo sviluppo di applicazioni scaricabili da Internet e fruibili su un browser commerciale. Questa strategia era ben mirata nel tentativo di creare un binomio WWW – Java, cosicche’ sul nuovo linguaggio/piattaforma ricadesse parte dell’enorme successo che Internet stava conoscendo. In pratica, mentre si faceva una gran parlare dello sviluppo di applet Java, in realtà il personale di maggiore esperienza tecnica ne intuiva le grandi potenzialità sul lato server.
Altro elemento fondamentali della strategia di marketing Sun consisteva nel promuovere Java non solo verso i tecnici ma anche verso gli utenti “comuni” per stimolare pure questi ultimi a richiedere soluzioni Java, anche se magari non ne comprendevano appieno le fondamenta tecniche.
Conclusioni
Con questo articolo abbiamo iniziato il nostro percorso relativo all’evoluzione di Java che ci porterà a illustrare le nuove feature introdotte con la versione Java SE7 e a proiettarci verso la versione 8.
Questo articolo, in particolare, è stato dedicato alle origini e ai fondatori di quello che probabilmente è il linguaggio moderno più famoso, quando Java ancora non si chiamava così, ma era denominato Oak.
Questa ricostruzione della “preistoria” di Java si è dimostrata tutt’altro che agevole, sia perche’ occorreva rielaborare in maniera coerente le non molte informazioni originarie, sia per il fatto che parte della documentazione originaria sembra essersi dissolta nel web: dopo l’acquisizione da parte di Oracle, sembrerebbe che diversi link non siano più funzionanti.
Abbiamo ripercorso il periodo che, dal 1991, vide un gruppo di 14 professionisti cominciare a ideare il linguaggio che avrebbe dovuto rimpiazzare il C++ fino ad arrivare al definitivo debutto di Java avvenuto tra il 1995 e 1996. Da un linguaggio che avrebbe dovuto occuparsi della logica di controllo degli elettrodomestici di largo consumo, Oak virò per un certo periodo verso il mercato della TV via cavo interattiva, fino a giungere alla strategia giusta basata sul supporto di Internet.
La storia di Java, da un punto di vista squisitamente tecnico, insegna anche un’altra grande e semplice lezione che spesso viene dimenticata. In molti casi, grandi soluzioni non richiedono idee rivoluzionarie o particolari stratagemmi, ma è spesso sufficiente fondare le proprie soluzioni sullo studio di idee che si sono dimostrate di successo, evitando al contempo gli errori che hanno creato seri problemi o addirittura decretato l’insuccesso dei propri predecessori.
Riferimenti
[1] Marco Tullio Cicerone, “Orator” XXXIV 120. 46 a.C.
[2] La pagina di Wikipedia dedicata a Oak
http://en.wikipedia.org/wiki/Oak_(programming_language)
[3] “Java Technology: the early years”
http://java-world-id.blogspot.com/2008/11/java-technology-early-years.html
[4] History of the Java programming language, WikiBooks
http://en.wikibooks.org/wiki/Java_Programming/History
[5] Heinz Kabutz, “Doing Things with Java that Should Not Be Possible Once Upon an Oak…”, luglio 2003
http://www.artima.com/weblogs/viewpost.jsp?thread=7555,
[6] “Java and unsigned int, unsigned short, unsigned byte, unsigned long, etc. (Or rather, the lack thereof)”, agosto 2009
http://www.darksleep.com/player/JavaAndUnsignedTypes.html
[7] Le specifiche di Oak
http://www.me.umn.edu/~shivane/blogs/cafefeed/resources/14-jun-2007/OakSpec0.2.zip
[8] UCSD Pascal
http://en.wikipedia.org/wiki/UCSD_Pascal
[9] Anna Kent, “Java- This Is Your Life (So Far)”, febbraio 2012
http://jaxenter.com/java-this-is-your-life-so-far.1-40584.html
[10] Scott Davison, “Kim Polese, The person who gave Java its now famous name […]”, 2004
http://www2.sys-con.com/itsg/virtualcd/java/archives/0101/davison/index.html
[11] James Gosling, “A Brief History of the Green Project”, 1998
http://www.skytel.co.cr/wireless-communications/research/1998/05-a.htm
[12] James Gosling “The Feel of Java”, giugno 1997
http://www.dfjug.org/thefeelofjava.pdf
[13] Jeff Schneider, “JDJ Interview: Arthur Van Hoff”, gennaio 1996
http://java.sys-con.com/node/35684
[14] Tarak G. Modi, “Sun Microsystems, Inc. vs Microsoft Corporation. A Case In Point”, primavera 1999
http://teknirvana.com/documents/Lawsuit.pdf
[15] Michael O’Connell, “Java: The inside story”, 1995
http://sunsite.uakom.sk/sunworldonline/swol-07-1995/swol-07-java.html
[16] Yakov Fain, “The unofficial History of Java Applets”
http://flexblog.faratasystems.com/2010/08/10/the-unofficial-history-of-java-applets