Italian (IT)

Da Java a EXE

Tratto da www.javastaff.com Autore originale Dmitry Leskov Tradotto da Luca Mattei

E' possibile creare un file exe a partire da un'applicazione java? Solitamente, alcuni problemi possono essere risolti senza creare un file EXE.

Il motivo principale della necessità di solito è semplificare la distribuzione di un'applicazione Java. Java compila le classi in bytecode proprietario (i file .class), che non è supportato direttamente dall'hardware dei PC. Quindi un programma Java ha bisogno della Java Runtime Environment (JRE) per essere eseguito, che so occupa di interpretare le istruzioni in bytecode e compilarle in codice nativo "on the fly". Questo obbliga l'autore del programma a richiedere che la corretta versione della JRE sia installata nei computer degli utenti finali. Generalmente, però, non si può assumere che gli utenti finali sappiano cosa è una JRE, o come verificare la versione di quella posseduta , o come installarne una versione diversa, senza creare problemi alle altre applicazioni java o alle applet visualizzate spesso. Se poi se anche si è sicuri che la versione corretta della JRE sia installata sulla macchina dell'utente finale, che su alcune classi di utenti è possibile, il comando da eseguire per richiamare l'applicazione è probilmente lungo:

java -Xmx200m -cp whatever.jar -Dsome.property MyApp

Sì, si può scrivere un file batch con il comando, del tipo: runme.bat, ma è molto più comodo distribuire la nostra applicazione, magari ad un collega o ad un insegnante o ad un amico, come un unico eseguibile da lanciare con un doppio click. O, magari, prevedere un processo di installazione (e di disinstallazione) nativo, che non crei conflitti con altre applicazioni. Per questo non è una sorpresa sapere che che il principale motivo del desiderio di convertire i programmi java in exe nasce dalla necessità di rendere più semplice e sicuro il deploy su utenti windows. La vera sorpresa, per i newbie, è che il JDK non offre una funzionalità del genere. Prima del J2SE 1.4 tutto quello che si poteva fare era:

JAR eseguibili: E' possibile rendere eseguibile una applicazione java attraverso un doppio click, racchiudendola in un jar eseguibile. per farlo bisogna specificare la classe principale della applicazione e ogni altro jar da includere nel file manifest contenuto:

Main-Class: MyAppMain Class-Path: mylib.jar

Quindi utilizziamo il tool "jar" contenuto del SDK, specificando l'opzione m e il nome del file manifest appena creato:

jar cvfm MyApp.jar MyApp.mf *.class *.gif

Ora per eseguire l'applicazione possiamo digitare:

java -jar MyApp.jar

e verrà letto nel file manifest il nome della classe della quale invocare il metodo main. Allo stesso modo, se la JRE è ben installata, basterà cliccare due volte sul jar per avviare la applicazione. Nota: Da J2SE 5.0, i file jar sono associati al launcher windows javaw, che non apre la finestra nera con la consolle. Quindi, se ne avete bisogno, dovrete far partire il jar da riga di comando o da un file batch. Se la vostra applicazione è composta da più jar, potete utilizzare il tool One-JAR per riunirli in un unico jar. Il maggior problema di questo metodo è la compatibilità con la JRE. La JRE di default potrebbe essere infatti troppo vecchia e non avere i necessari Java Optional Packages (conosciuti prima come Standard Extensions). Per esempio, se la vostra applicazione usa il package java.nio introdotto dalla versione 1.4.2, non funzionerà con la JRE versione 1.3.x. Allo stesso modo, se usa JavaMail 1.3, e la JRE installata ha JavaMail 1.2 o non la possiede affatto, il jar non verrà eseguito.

PRO:

  • Non si usano tool di terze parti.
  • Multipiattaforma

CONTRO:

  • Le applicazioni non partono se non si ha una JRE correttamente installata.
  • Le applicazioni non funzionano se le APIs utilizzate non sono presenti nella JRE di default.
  • Bisogna informare gli utenti che i file JAR sono cliccakabili.

RISORSE:

  • The Java Archive (JAR) File Format

TOOLS:

  • One-JAR

Java Web Start Fortunatamente, per risolvere questi problemi di compatibilità, dal SDK 1.4 è presente un tool che facilita la vita allo sviluppatore. Java Web Start (JWS) e il suo protocollo Java Network Launch Protocol (JNLP) permette la distribuzione delle applicazioni java direttamente da un webserver standard. L'utente finale può iniziare l'installazione semplicemente cliccando su un URL. Se Java Web Start non è presente nel sistema, verrà proposto il download e l'installazione del tool. Se necessario, JWS provvederà poi ad avviare download ed installazione della JRE corretta e di eventuali package aggiuntivi. L'applicazione viene quindi lanciata e rimane pronta e nascosta nel sistema dell'utente finche' l'utente non la richieda nuovamente dall'URL associato, senza reinstallarla a meno che la versione della applicazione non sia obsoleta. In tal caso verrà aggiornata. Un'altra caratteristica interessante di Java Web Start è la capacità di far girare le vostre applicazioni in una SandBox, un container "sicuro". Ma a differenza della SandBox delle Applet, l'applicazione può accedere alle risorse native, come filesystem, stampanti e alla memoria degli appunti attraverso le JNLP Api, dopo aver chiesto il permesso all'utente, ovviamente. Java WebStart è disponibile per piattaforme Windows, Linux, Solaris e Mac OsX a partire dalla versione 10.1. Ci sono anche implementazioni di terze parti del protocollo JNLP ed alcune includono tool per la preparazione di un package adatto a JWS. Ma passiamo ai difetti. Innanzitutto il WebServer che ospita le applicazioni deve supportare il tipo mime associato a Java Web Start:

application/x-java-jnlp-file

Alcuni providers potrebbero non permetterlo. Inoltre per utilizzare le funzionalità di versioning e il supporto agli updates, c'è bisogno di un webserver in grado di supportare servlets, cgi-bin scripts, etc. Lato client, non ci dovrebbero essere problemi nel riconoscere il MIME type, per lo meno nei browser più popolari. In alcuni browser più di nicchia invece potrebbe essere necessario configurarli manualmente. Abilitare JNLP in un'applicazione dovrebbe richiedere modifiche minime e la creazione di un set di files jar. Prima della J2SE 5.0, JWS aveva veramente poco da offrire, in termini di integrazione desktop, limitandosi a creare una icona sul desktop e/o un collegamento nel menu Start. In Windows, l'applicazione non apparirà nelle entry in "Installazione Applicazioni", quindi l'utente dovrà lanciare Java Web Start per disinstallare l'applicazione. Infine, si vede la necessità di una interfaccia utente più pulita per JWS. Allo stato attuale (J2SE 5.0) gli utenti si trovano a interagire con orribili finestre con messaggi incomprensibili. Lato client, non ci dovrebbero essere problemi nel riconoscere il MIME type, per lo meno nei browser più popolari. In alcuni browser più di nicchia invece potrebbe essere necessario configurarli manualmente. Abilitare JNLP in un'applicazione dovrebbe richiedere modifiche minime e la creazione di un set di files jar. Prima della J2SE 5.0, JWS aveva veramente poco da offrire, in termini di integrazione desktop, limitandosi a creare una icona sul desktop e/o un collegamento nel menu Start. In Windows, l'applicazione non apparirà nelle entry in "Installazione Applicazioni", quindi l'utente dovrà lanciare Java Web Start per disinstallare l'applicazione. Infine, si vede la necessità di una interfaccia utente più pulita per JWS. Allo stato attuale (J2SE 5.0) gli utenti si trovano a interagire con orribili finestre con messaggi incomprendibili. Riassumento, JWS può essere valida una opzione in ambienti controllati, come le intranet, ma non è pronto per il mercato consumer, per il quale sono preferibili le soluzioni seguenti.

Java Launcher e Wrappers custom Quando un programma Java è invocato utilizzando uno dei metodi discussi sopra (file batch, jar eseguibile, JWS/JNLP), il sistema operativo esegue un lancher java fornito dalla JRE. La versione windows della JRE ha launchers separati per le applicazioni command line e quelle grafiche, rispettivamente java.exe e javaw.exe. Come risultato, tutte le applicazioni java in esecuzione hanno lo stesso nome nel Task manager e la stessa icona nella taskbar o nel pannello "alt-tab". Se si hanno più di un applicazione java in esecuzione, non si ha modo di distinguere fra le diverse istanze di java nel task manager. Praticamente, questi launchers sono solamente piccoli programmi nativi che caricano la JVM da una dll (shared library) ed eseguono le tue applicazioni usando le Invocations API. Queste api fanno parte delle Java Native Interdace (JNI), quindi standard, e molto semplici. Questo rende relativamente semplice scrivere un nostro launcher con un nome e un'icona unici. Quello che bisogna fare è trovare una JRE disponibile sul sistema dell'utente (o includerne una nell'applicazione), caricare e inizializzare la JVM e far girare l'applicazione su di essa.

Tool Java per creare Setup Se si necessita solo di installare una copia privata della JRE insieme alla propria applicazione e creare un collegamento che la esegua su tale JRE, si può utilizzare qualsiasi generatore di setup. Comunque, utilizzare un tool basato su java potrebbe avere dei benefici:

  • Rilevare al momento dell'installazione eventuali JRE presenti ed eventuale download
  • Generazione di un launcher nativo
  • Parametri JVM editabili dall'utente
  • Redirezione degli stderr e stdout per salvare log ed eccezioni
  • Registrazione delle applicazioni Java come servizi Windows o demoni Unix

Questa categoria è la più diversificata in termini di prezzo e funzionalità. Le differenze sono spiegate qui sotto: I tool Windows centrici, come Advanced Installer for Java permettono di creare installativi MSI. I tool multipiattaforma possono generare installativi per più piattaforme: Windows, Linux, Mac OS. Install4j è uno di questi. Ci sono anche Tool che permettono di creare installativi unici che girino su più piattaforme. Tali installativi sono essenzialmente jar eseguibili con logiche specifiche per gli ambienti nativi, riconosciuti a runtime. InstallAnywhere è forse il più conosciuto della categoria, ma se il suo prezzo è oltre il vostro budget, considerate il più economico JExpress o IZPack, Open Source. Infine, c'è un tool che li racchiude tutti, InstallShield che può creare sia MSI per Windows che installativi closs-platform,anche per server o dispositivi mobili, per qualsiasi tipo di applicazione e per una moltitudine di sistemi operativi. E sì, supporta il riconoscimento della JRE, l'installazione in bundling, i launcher nativi e così via.. Comunque, per le installazioni semplici e dirette, InstallShield è un peso inutile. Ricordate anche che InstallShield e InstallAnywhere mirano agli sviluppatori enterprise ed i loro prezzi sono conseguentemente elevati. Tutte queste soluzioni non risolvono il problema fondamentale menzionato nella prima sezione di questo articolo. Sia creando un jar eseguibile o un sofisticato installativo, l'applicazione continua ad essere distribuita come bytecode platform-indipendent. Nei primi giorni di Java, l'unico modo di eseguire un programma java su di un comune PC, era di interpretare tale bytecode. Oggi, qualsiasi implementazione J2SE decente contiene un compilatore Just-in-Time (JIT) che compila i metodi eseguiti frequentemente in codice nativo. Così è abbastanza naturale passare un passo avanti e compilare tutta l'applicazione prima di distribuirla. Vediamo quali tool ci permettono di farlo.

Compilatori Ahead-Of-Time I compilatori AOT sono conosciuti anche come "compilatori statici" o "compilatori di codice nativo". Quest'ultima denominazione è la più usata e, come spesso succede, la meno corretta dal punto di vista tecnico, dato che anche i compilatori JIT producono codice nativo. Un compilatore Ahead-Of-Time (AOT) prende in input i vostri file jar o class e produce un eseguibile convenzionale in linguaggio nativo, come un EXE Windows o un binario ELF per Linux. Così come qualsiasi altra soluzione tecnica, anche questa ha i suoi vantaggi e svantaggi.

Vantaggi:

  • Performance. Un compilatore JIT funziona come una applicazione in background e condivide la cpu e le risorse di memoria con l'applicazione che compila e con qualsiasi altra applicazione in esecuzione. Un compilatore AOT gira sul sistema dello sviluppatore senza vincoli di tempo o di risorse. Per questo può, potenzialmente, utilizzare ottimizzazioni di risorse più potenti, rendendo il codice migliore.
  • Protezione della proprietà intellettuale. Il bytecode Java è molto facile da decompilare, basta cercare "download java decompiler" per ottenere il codice sorgente di qualsiasi applicazione java in 5 minuti. Sì, è possibile offuscare i nomi delle classi e dei metodi pubblici ai quali non si accede via reflection, ma l'offuscamento del controllo di flusso può rendere il bytecode non verificabile dalle future JVM e rendere impossibili le ottimizzazione implementate dai compilatori JIT. Infine, criptare il bytecode non lo protegge del tutto, qualsiasi algoritmo di criptaggio si usa. D'altra parte, il codice nativo prodotta da un compilatore AOT ottimizzante è troppo complesso da essere sottoposto a reverse engineering, quanto quello di applicazioni sviluppate in C++. Inutile da dire, non ci sono prestazioni perse. Se si è interessati a proteggere la propria proprietà intellettuale, si dia uno sguardo alla compilazione nativa.
  • Percezione dell'utente. Le applicazioni Java Client soffrono spesso della cossidetta sindrome del ciclo di riscaldamento. Avviare un programma java richiede l'interpretazione del bytecode, la sua profilazione e la compilazione JIT. Per questo i programmi Java tendono a partire più lentamente dei loro rivali nativi e l'iniziale tempo di risposta di una applicazione grafica Java è molto peggiore di quello effettivo dopo che è stata usata parecchie volte, che sono le due maggiori ragioni per cui Java è ancora percepita come lenta da molti utenti. Un eseguibile nativo gira direttamente sull'hardware, senza l'overehad interpretazione-profilazione-compilazione, così può avviarsi più velocemente ed ottenere migliori tempi di risposta.

Svantaggi:

  • Peso sul disco. Il bytecode del Java è stato progettato per la compattezza, a un livello molto più elevato del set di istruzioni macchina. Si pensi che un eseguibile prodotto da un compilatore AOT sia 2-4 volte più grande dell'originale file jar.
  • Applicazioni dinamiche. Le classi che l'applicazione carica dinamicamente a tempo di esecuzione possono essere non disponibili al sviluppatore. Queste librerie possono essere plugin di terzi, proxy dinamici ed altre classi generate a tempo di esecuzione e così via. Così il sistema deve includere un interprete di bytecode Java e/o un compilatore JIT. Inoltre, generalmente solo le classi che sono caricate dal sistema o dal classloader dell'applicazione possono essere precompilate in codice nativo. Così le applicazioni che usano i classloaders custom possono soltanto essere parzialmente precompilati.
  • Ottimizzazioni per Hardware specifico. Un compilatore JIT presenta un vantaggio potenziale rispetto ai compilatori AOT in quanto può selezionare pattern di generazione di codice secondo la reale configurazione hardware su cui sta girando l'applicazione. Per esempio, può utilizzare le estensioni Intel MMX/SSE/SSE2 per velocizzare i calcoli in virgola mobile. Un compilatore AOT deve o produrre codice per il minor comun denominatore oppure diverse versioni per i più metodi più CPU-intensivi, aumentando il volume di codice.

C'è anche un comune pregiudizio che la compilazione AOT uccida la portabilità Java. Questo non è il caso, dato che il codice sorgente non necessita di essere modificato e si può sempre distribuire il bytecode per le piattaforme per cui non esiste un compilatore AOT. (Si perderebbe ovviamente il vantaggio di protezione del codice). Per quanto riguarda i tools, nel 2000 ne erano presenti una mezza dozzina, ma solo un paio sono sopravvissuti, si tratta di Excelsior JET e di GCJ (Gnu Compiler for Java). (Se siete interessati al campo embedded, date un'occhiata a NewMonics PERC, che si indirizza a J2ME CDC ed ha anche un supporto limitato a J2SE 1.3.

This website uses cookies to ensure you get the best experience on our website.