Generazione di codice dinamico per la realizzazione di catene di servizi componibili Progetto di Reti di Calcolatori LS A.A. 2007/08 Studente: Silvia Cereda (matr )
Obiettivo Creazione di un ambiente di integrazione e composizione di servizi atomici dislocati su nodi diversi Contesto Java EE Servizi come metodi invocabili su EJB Utilizzo di un supporto per la generazione dinamica del bytecode Maggiore efficienza rispetto all'uso di un compilatore
Manipolazione del bytecode Manipolazione dinamica del codice come requisito fondamentale in sistemi aperti a variazioni Maggiore efficienza rispetto all'utilizzo di un compilatore Reflection utile ma poco adatta ad invocazioni frequenti Necessità di agire anche su codice preesistente
Framework considerati BCEL ( ) Implementazione ad “alto livello” Non vengono maneggiati i dettagli interni del formato delle classi Java Utilizzo di API per i vincoli statici delle classi Componenti binari, strutture dati delle specifiche JVM,... API per contenuto dinamico Creazione e trasformazione di metodi e attributi
Framework considerati Serp ( ) Obiettivo: massimizzare l'efficienza dei costi minimizzando i costi Facilità di utilizzo Possibilità di lavorare con metodi di “alto livello” potendo accedere anche ai dettagli di basso livello Lentezza nella generazione delle classi Dispendio di memoria per la generazione delle classi
Framework considerati ASM ( ) Elaborazione delle classi sequenziale basata sull'utilizzo di un Visitor Non mantiene strutture persistenti in memoria Elaborazione a catena delle classi ClassReader per il parsing del bytecode ClassAdapter per filtrare l'output ClassWriter per scrivere la classe
Confronto performance ASM è la soluzione più efficiente! A) Utilizzo di un classloader standard B) Serializzazione e deserializzazione di ogni classe prima della compilazione C) Ricomputazione, dopo l'esecuzione di B), della massima grandezza dello stack di ogni metodo Confronto tra le performance dei framework analizzati: misura del tempo di caricamento di un “gran numero di classi” da un.jar Fonte:
Architettura
Brick: contiene un servizio elementare Executor: accetta le richieste, ottiene la catena desiderata dal Coordinator, la esegue e restituisce il risultato all'utente Coordinator: interpella un ClassLoader per avere la catena esistente,se non esiste avverte all'ASMBlackSmith di crearla ASMBlackSmith: crea il bytecode delle catene
Richiesta catena - askChain()
ASMBlackSmith Riceve i Brick ordinati che formano la catena Invoca ArrayList build(ArrayList bricks) Delega all'ASMHammer la costruzione della catena Parte statica Inizializzazione del sistema, signature, costruttore Parte dinamica Per ogni Brick crea il bytecode relativo al servizio Restituisce il bytecode della catena formata dalla serie dei Brick
Chain Invocazione dal cliente per l'esecuzione della catena: Object execute(actualPar) actualPar: array di parametri d'invocazione ordinati Object per la generalizzazione dei parametri di ritorno Chain implementa l'interfaccia IChain e il suo metodo execute
Conclusioni E' stato realizzato un servizio di composizione di servizi elementari dislocati su nodi diversi E' stata realizzata un'interfaccia web per la registrazione e utilizzo di tali servizi e la composizione ed utilizzo di catene di servizi Alta efficienza data dall'utilizzo del framework ASM A regime In fase di compilazione delle cateen
Sviluppi futuri Aggiunta di controlli di sicurezza nelle fasi di utilizzo Sviluppo di un framework completo per la composizione di servizi Creazione ed utilizzo di un meta-linguaggio per la composizione di servizi