Utente:LoStrangolatore/corsojava/lez01/Premesse

Da Wikiversità, l'apprendimento libero.

Cos'è un programma[modifica]

Un programma è scritto per una macchina astratta

Un programma è un insieme di uno o più file contenenti istruzioni che lavorano su un certo input e restituiscono un certo output. Questo vale per tutti i tipi di programmi: dal software di sistema, al software applicativo, ai giochi.
Il tipo e il formato delle istruzioni variano in base a determinati fattori, però sono sempre scelti in modo che il risultato possa essere eseguito su un modello astratto di calcolatore scelto a priori, e dotato di specifiche di funzionamento ben definite e già note. Questo modello definisce una macchina astratta che prende in ingresso il testo del programma e lo esegue.

L'ambiente su cui il programma sarà eseguito (calcolatore + sistema operativo + altri eventuali strati di astrazione software) non è altro che una specializzazione concreta di questo modello, di cui rispetta le regole formali. Queste regole sono chiamate specifiche, e sono come un contratto che definisce determinati vincoli comuni, scelti per convenzione, e che, in questo modo, può garantire piena compatibilità tra programmi e ambienti di esecuzione, se entrambi rispettano tali regole comuni.

Tutto ciò che aderisce correttamente alle specifiche può essere considerato un'implementazione della macchina: anche un essere umano che legga il programma istruzione per istruzione e che esegua le computazioni su carta. Un altro esempio: la lista della spesa può essere considerata un programma scritto in un certo linguaggio (italiano), e la persona che la legge al supermercato può essere considerata un esecutore che scorre le istruzioni scritte sul foglio e le svolge compiendo operazioni di trasferimento di oggetti (quindi vere e proprie operazioni di input/output) da e verso gli scaffali del negozio e da e verso il carrello.

I vantaggi di usare un modello astratto di calcolatore

Dove esistono delle specifiche, c'è uniformità di comportamento, e quindi interoperabilità. In programmazione, ciò significa che (in teoria) è possibile eseguire uno stesso programma su ambienti diversi senza doverlo riscrivere o riprogettare per ciascuno di essi.[1] Ciò rende possibile scrivere un programma che funzioni su un numero illimitato di dispositivi diversi, costruiti in tempi diversi e secondo tecnologie diverse, ma conformi alle stesse specifiche.

Linguaggi di programmazione

Il linguaggio riconosciuto da una macchina è chiamato linguaggio di programmazione. Nello sviluppo del software, si fa uso di macchine astratte che riconoscono linguaggi abbastanza intuitivi, perché simili al linguaggio umano (di solito l'inglese), e che si chiamano linguaggi di alto livello. Esistono macchine che riconoscono linguaggi molto più sintetici e compatti, ma anche criptici, e che spesso sono più facili da implementare in hardware; questi sono i linguaggi di basso livello.

Compilazione[modifica]

L'idea di base

Una macchina può servirsi di un'altra macchina per eseguire del tutto o in parte le istruzioni che compongono un programma.

Ad esempio, una persona che si serve di una calcolatrice è un esecutore, che riceve in ingresso un'espressione matematica e restituisce in output un numero, ma che non svolge il calcolo autonomamente: invece, lo delega ad un altro esecutore, in questo caso la calcolatrice, che accetta in ingresso solo due numeri alla volta.

Ciò vuol dire che si può avere una macchina capace di svolgere compiti complessi (per es. una persona che sa risolvere equazioni) che, a sua volta, si serve di una macchina che è limitata a compiti più semplici (per es. una calcolatrice, che svolge calcoli tra coppie di numeri).

Utilità pratica

Questo stratagemma è particolarmente utile nello sviluppo del software, perché permette di far sì che un programma scritto in un linguaggio ad alto livello sia eseguito da una macchina che riconosce un linguaggio di livello più basso.[2] Il trucco sta nell'aggiungere una operazione intermedia di traduzione: il programmatore scrive il testo del programma come se avesse a che fare con una certa macchina astratta, dopodiché uno strumento automatico lo trasforma in una versione equivalente, caratteristica di una macchina più semplice.[3] Questo strumento si chiama compilatore e l'operazione da esso svolta si chiama compilazione.

Il testo di un programma si chiama codice. Il testo scritto in un linguaggio di alto livello si chiama codice sorgente; il testo prodotto dal compilatore si chiama codice oggetto.

Conseguenze

Lo sviluppo di un programma in un linguaggio di alto livello prevede tre fasi:

  1. si scrive il testo del programma secondo le regole del linguaggio scelto;
  2. si avvia il compilatore, che prende come input il testo del programma, e restituisce in output una versione equivalente ma scritta in un linguaggio di basso livello;
  3. si esegue il programma su un certo ambiente di esecuzione.

Il linguaggio Java[modifica]

Java è un linguaggio di alto livello. Le specifiche di linguaggio, cioè il riferimento ufficiale che ne definisce le regole, prendono il nome di Java Language Specification e sono disponibili qui.

Il compilatore del Java, esattamente come ogni altro compilatore, prende in ingresso un programma e restituisce una forma equivalente, scritta in un formato che sia comprensibile ad un modello astratto di processore. Il codice oggetto di un programma Java si chiama bytecode.

La Java Virtual Machine

La macchina astratta verso la quale ogni programma Java è destinato prende il nome di Java Virtual Machine o JVM. Questa macchina prende in ingresso il codice compilato di un programma Java, e si assicura che esso sia eseguito.

Spesso il processore dell'elaboratore in uso non supporta le istruzioni definite dalle specifiche della macchina virtuale, quindi la combinazione sistema operativo + processore non è sufficiente. In questo caso, la virtual machine viene aggiunta come strato software, in modo che l'ambiente di esecuzione risultante (Java Virtual Machine + sistema operativo + processore) obbedisca alle specifiche della macchina astratta. In parole semplici, l'utente scarica ed esegue la macchina virtuale come interprete per l'esecuzione del programma Java.
Si è scritto spesso, non sempre: infatti, è possibile realizzare un sistema operativo che sia in grado di avviare direttamente un programma Java, senza il supporto di uno strato software aggiuntivo. Inoltre, è possibile perfino costruire un processore il cui linguaggio macchina coincida con lo instruction set definito dalle specifiche della macchina virtuale Java, nel qual caso la macchina virtuale è il processore stesso e non si rende necessario un ulteriore strato software.

Il vantaggio di avere una macchina virtuale

Il vantaggio principale di questo approccio è la portabilità. Altri linguaggi di alto livello prevedono che il programma sia compilato direttamente nel linguaggio riconosciuto dall'ambiente di esecuzione, e ciò significa che il programma deve essere ricompilato ogni volta che si prevede di usarlo su un sistema operativo o processore con differenti specifiche. Il linguaggio è unico, ma diverse sono le specifiche degli ambienti di esecuzione (il formato accettato dal sistema operativo, i meccanismi di accesso allo hardware o alle librerie software, ecc.). Ciò significa che il testo del programma deve essere scritto avendo cura che sia compatibile con le varie specifiche, e ciò può richiedere che una parte del programma sia riscritta più volte, con codice specifico per ognuno di tali ambienti.

Al contrario, la macchina virtuale fornisce un ambiente di esecuzione unico, in quanto è definita apposta per essere indipendente dai processori e dai sistemi operativi in commercio, e quindi indipendente dalle singole macchine astratte da essi definite. Chi realizza il programma dovrà scriverlo e compilarlo una sola volta, perché a fornire la corrispondenza con processori e sistemi operativi ci pensano gli sviluppatori della macchina virtuale.

Java non è l'unico linguaggio basato su macchina virtuale.

Note[modifica]

  1. Ciò è vero, in teoria: infatti, se le specifiche interessano solo una parte del comportamento della macchina, può risultare necessario riscriverlo per ciascuno degli ambienti sui quali si ha intenzione di eseguirlo. Ad esempio, questo è il caso di quelle piattaforme che non forniscono un accesso unificato alle risorse hardware e software del sistema sottostante.
  2. Dal punto di vista del programma, e del programmatore, ciò equivale ad ottenere una "implementazione concreta" di una macchina astratta, che si serve di un'altra macchina astratta, definita a priori e in grado di riconoscere un linguaggio diverso.
  3. Questo meccanismo può essere ripetuto un numero arbitrario di volte, fino ad arrivare all'esecutore finale, che è il processore, e che implementa una macchina dotata di un suo linguaggio specifico, che è il linguaggio di livello più basso e che è chiamato linguaggio macchina, e che è tipicamente composto di istruzioni che possono essere facilmente eseguite facendo correre segnali elettrici all'interno della circuiteria del processore stesso.