Come usare il debugger in Netbeans

Usare il debugger.
(E' il momento di abbandonare System.out.println(".."))

Il Debugger consente di analizzare il flusso del programma, istruzione dopo istruzione, ad esempio analizzando lo stato delle variabili, lo stack delle chiamate e i thread in esecuzione.

Anche nella programmazione su dispositivi mobili il debugger è di certo uno strumento preziosissimo.

Di seguito cercherò di dare delle indicazioni su come usare questo strumento con
Netbeans 5.5.1.

Il punto in cui decidiamo di fermare il codice per analizzare lo stato della jvm (ad esempio le variabili) si chiama Breakpoint.
L'inserimento di un breakpoint avviene cliccando sulla parte grigia che precede l'editor di testo di netbeans:



La linea di codice viene evidenziata!

Per avviare la midlet e analizzarla con il debugger bisogna premere F5.
Non appena il flusso del programma arriva al breakpoint, l'esecuzione si blocca e il colore della linea evidenziata cambia.

In questo istante è possibile conoscere l'attuale valore delle variabili

  • Passandoci di sopra con il mouse
  • Leggendo il tab sottostante "Local Variables" (solo per le variabili locali)
  • Premendo CTRL+F9 e analizzando l'espressione proposta.

Se qualche variabile risulta di particolare interesse durante l'analisi di debugging allora possiamo aggiungere su di essa una Watch.
Per aggiungere una Watch basta selezionare la variabile, anche senza debugging attivo, e premere CTRL+Maius+F7.
Da questo momento durante il debugging tutte le variabili "Watch" vengono raggrupate nel tab "Watches".

Se siamo interessati a conoscere lo stato del sistema all'istruzione di codice successiva è sufficente premere F8, F7, o CTRL+F7

  • F8 indica l'avanzamento all'istruzione successiva.
  • F7 indica l'avanzamento all'istruzione successiva. Se tale istruzione è un metodo l'esecuzione si fermerà alla prima istruzione interna al metodo
  • CTRL+F7 Se siamo entrati all'interno di un metodo con F7, e non siamo più interessati all'analisi interna del metodo e vogliamo ritornare al livello esterno della chiamata questa è l'opzione giusta.

Questi concetti basiliari sono adattabili anche per altri ambienti di sviluppo e linguaggi di programmazione.

Nello sviluppo su Java ME è possibile effettuare il debugging sull'emulatore usando semplicemente il WTK, per quanto riguarda invece il debugging sui dispositivi, bisogna verificare se il produttore mette a disposizione un SDK con relativa funzionalità per il debugging (ad esempio come avviene per SonyEricsson).





Come firmare una MIDlet suite

Firmare una MIDlet suite

Lo sviluppatore che intende firmare una MIDlet suite deve avere un certificato di firma per il codice conforme alle specifiche X.509.

Il dispositivo usa una serie di certificati root per validare il certificato della MIDlet suite.

Il certificato o i certificati usati per firmare la midlet verranno inclusi nel file JAD usando l'attributo MIDlet-Certificate-<n>-<m>.(<n>-<m> rappresenta la catena di certificati eventualmente usata)

Viene generato un digest SHA1 del jar contenente la MIDlet suite firmato con il certificato contenuto nel jad

Tale digest viene memorizzato nel JAD usando l'attributo MIDlet-Jar-RSA-SHA1.

Processo di autenticazione

Viene letto il certificato dall'attributo MIDlet-Certificate

Tale certificato viene validato usando i certificati root presenti nel dispositivo

Viene estratta la chiave pubblica dal certificato e viene usata per decriptare l'attributo MIDlet-Jar-RSA-SHA1.

Il risultante valore sarà il digest SHA1 del JAR.

L'implementazione MIDP calcola lo stesso digest dal jar.

Se entrambi i digest corrispondono la MIDlet suite viene autenticata e viene assegnato il relativo dominio di protezione.

Processo di richiesta del certificato digitale

Attraverso il WTK (Wireless Toolkit) della Sun si genera un coppia di chiavi

  • Aprire il WTK
  • Aprire Utilities
  • Aprire Sign MIDlet
  • Scegli KeyStore
  • Clicca su New KeyPair
  • Inserire i valori (tali valori devono essere sempre gli stessi ogni volta che vengono richiesti in altre fasi)

Scegliere la coppia creata, e Generare un CSR

  • Scegli KeyStore
  • Clicca su Generate CSR

Inviare tale CSR all'autorità(es. Verisign, Thwate) presso la quale si vuole acquistare il certificato.

La tipologia di certificato da acquistare è quella relativa alla firma del codice java.
Quando si acquista un certificato infatti esso deve essere specifico per l'utilizzo che si intende fare.

Conservare il keystore ovvero il file keystore.ks che si trova all'interno della cartella appdb del WTK.
All'interno di tale file è contenuta la coppia di chiavi che dovrà essere utilizzata in un secondo momento per la firma.
Perdendo tali chiavi la firma acquistata non è più utilizzabile.

Dopo qualche giorno arriva un file di testo contenente il certificato digitale rilasciato dall'autorità.

Processo di "installazione" certificato digitale

Il certificato inviato dall'autorità deve essere inserito all'interno del keystore.
Tale operazione può essere fatta con il WTK, con l'apposita funzione Import Certificate.

Alternativa è quella di usare un utilità free e open source: Portecle

Mediante portecle è possibile aprire il file keystore.ks.

Una volta selezionato l'alias che rappresenta le chiavi create per l'occasione
Cliccando il tasto destro è possibile selezionare "import CA reply" e quindi importare il certificato acquistato

Salvando il keystore possiamo quindi utilizzarlo per firmare le midlet, ad esempio importando tale keystore su netbeans





Ottimizzazioni per midlet - Java ME - parte 2

Suggerimenti per ottimizzare applicazioni java ME


In questo articolo si concentra l'attenzione sulla riduzione delle dimensioni, in termini di kb, di un jar.


Usare meno classi possibili.

L'algoritmo di compressione funzionerà meglio con poche classi con tanto codice rispetto a tante classi contenenti poco codice in quanto ha maggiori quantità di dati su cui lavorare.

Usare un offuscatore tipo proguard peraltro già incluso nel mobility pack di netbeans

Nel caso in cui si usi netbeans ricordarsi di settare al massimo il livello di offuscamento

Ricomprimere il jar finale con un software di compressione basato sul formato zip.
Tali compressori spesso sono migliori rispetto all'utitility di compressione jar presente negli ide. (esempio KZip)


Raggruppare le risorse

Si parte dal presupposto che l'algoritmo di compressione riesce a dare risultati migliori se la quantità di dati da comprimere è maggiore.
Quindi per ciò che riguarda le risorse che si inseriscono all'interno del jar si può pensare di raggrupparle all'interno di uno stesso file. Ciò comporta la creazione di un applicativo per la generazione di tale file di raggruppamento e una classe per il caricamento dei dati raggrupati. A tal proposito
esiste già un tool BamFS, il cui compito è proprio quello di generare un unico file di risorse, e una classe statica per il caricamento di tali risorse.

Ottimizzare le PNG

Usare il massimo livello di compressione.
Usare una palette di colori il più ridotta possibile.
E' più conveniete usare una png con i diversi frame piuttosto che una png per ogni frame
usare ottimizzatori tipo PNGCrush, OptiPNG o PNGOUT
Usare il massimo livello di compressione.
Usare una palette di colori il più ridotta possibile.
E' più conveniete usare una png con i diversi frame piuttosto che una png per ogni frame
Usare ottimizzatori tipo
PNGCrush, OptiPNG o PNGOUT
Eliminare dalle png tutte le informazioni aggiuntive tipo la data di creazione, i commenti etc.


Ottimizzazioni per midlet - Java ME - parte 1

Suggerimenti per ottimizzare il codice java su ME

Di seguito ho raccolto una serie di consigli applicabili allo sviluppo di applicazioni su piattaforma java me. Tali pratiche spesso vanno contro i principi della buona programmazione object oriented ma nello stesso tempo permettono di ottenere ottimizzazioni sui dispositivi con risorse limitate.



Preferire sempre l'uso di array rispetto ai Vector.
Se è cmq necessario utilizzare strutture dinamiche costruirsi una classe ad hoc che incrementa il proprio spazio secondo la logica migliore per quel tipo di applicazione.

Preferire l'uso di char array rispetto alle stringhe.

Usare per le concatenazioni di stringhe lo StringBuffer e non l'operatore di concatenazione "+"


Sostituire le operazioni di moltiplicazione e divisione per operandi potenze di 2 con operazioni di shift
op1 >> op2 corrisponde a op1:2^op2
op1 << op2 corrisponde a op1*2^op2

Evitare quando possibile uso di metodi synchronized
Sono i piu’ lenti in assoluto causa del check sui monitors


Usare quando possibile tipi che richiedono meno memoria
Ad esempio usare "short" per valori sappiamo non supereranno 255

Evitare il più possibile blocchi try catch, se proprio necessari mantenerli all'esterno dei loop

Evitare l'uso di package.
Durante la fase di sviluppo magari avvalersi di tale possiblità ma eliminarla prima del rilascio finale dell'applicazione.


Quando possibile eliminare i loop a favore di codice ripetuto.
for (int i =0 ; i<10; i++) {..Faiqualcosa();.. } può essere sostituito per ridurre bytecode generato e aumentare le prestazioni in 10 chiamate a Faiqualcosa();

Nelle espressioni di confronto preferire il confronto con i valori: 0, null, false

Usare i blocchi switch rispetto ai blocchi if.

I primi infatti vengono tradotti nelle jump tables quando avviene la compilazione creando meno bytecode e migliorandone le performance.

Accedere alle variabili direttamente dichiarandole public.

Nonostante tale pratica non rispetti i principi della programmazione OO tale tecnica consente un accesso più veloce e snello rispetto ai metodi di incapsulamento ("get.. e set..").

Preferire variabili locali rispetto a campi della classe.

Usare le classi interne se le funzionalità di tale classe sono "vicine" alla classe "contenitore".

Settare a null i riferimenti ad oggetti non più utilizzati.

Dichiarare le costanti "final static".

Il compilatore inserirà il valore direttamente all'interno della classe stessa.Usando ad esempio proguard tale ottimizzazione viene cmq persa.