java et la réflexivité. java reflection is useful because it supports dynamic retrieval of...

47
Java et la réflexivité

Upload: benedicte-michaux

Post on 03-Apr-2015

114 views

Category:

Documents


1 download

TRANSCRIPT

Page 1: Java et la réflexivité. Java reflection is useful because it supports dynamic retrieval of information about classes and data structures by name, and

Java et la réflexivité

Page 2: Java et la réflexivité. Java reflection is useful because it supports dynamic retrieval of information about classes and data structures by name, and

Java reflection is useful because it supports dynamic retrievalof information about classes and data structures by name, and allows for their manipulation within an executing Java program. This feature is extremely powerful and has no equivalent in other conventional languages such as C, C++, Fortran, or Pascal.

Glen McCluskey

has focused on programming languages since 1988.He consults in the areas of Java and C++ performance, testing, and technical documentation.

Page 3: Java et la réflexivité. Java reflection is useful because it supports dynamic retrieval of information about classes and data structures by name, and

Réflexivité en Java ?

La réflexivité en Java permet à un programme Java de s’examiner en cours d’exécution de manipuler ses propriétés internes.

Par exemple, une classe Java peut obtenir le nom de tous ses membres.Utilisation connue de la réflexivité : l’édition sous EclipseL’outil utilise la réflexivité pour obtenir liste des méthodes publiques qui peuvent être envoyées à une instance d’une classe

Page 4: Java et la réflexivité. Java reflection is useful because it supports dynamic retrieval of information about classes and data structures by name, and

Que peut on faire ?

Obtenir des informations sur les classesSimuler l’opérateur instanceofDécouvrir la liste et le descriptif des méthodes Obtenir des informations sur les constructeursAvoir des informations sur les variables

Invoquer des méthodes, des constructeurs, affecter des variablesCréer des objets et des tableaux

dynamiquement lors de l ’exécution du programmesans connaître à la compilation le nom et les arguments d’une méthode / constructeur le nom de la variable le type des objets, des tableaux….

Page 5: Java et la réflexivité. Java reflection is useful because it supports dynamic retrieval of information about classes and data structures by name, and

Réflexivité = un package Java

java.lang.reflect.*

des classes: Object

AccessibleObject

Constructor

Field

Method Array

InvocationTargetException

Modifier

ReflectPermission

une interface : Member

Page 6: Java et la réflexivité. Java reflection is useful because it supports dynamic retrieval of information about classes and data structures by name, and

Un exemple simplepublic class DumpMethods { public static void main(String args[]) { try { Class c = Class.forName(args[0]); Method m[] = c.getDeclaredMethods(); for (int i = 0; i < m.length; i++) System.out.println(m[i]); } catch (Throwable e) {System.err.println(e);} } }

public java.lang.Object java.util.Stack.push(java.lang.Object)public synchronized java.lang.Object java.util.Stack.pop()public synchronized java.lang.Object java.util.Stack.peek()public boolean java.util.Stack.empty()public synchronized int java.util.Stack.search(java.lang.Object)

java.util.Stack

Page 7: Java et la réflexivité. Java reflection is useful because it supports dynamic retrieval of information about classes and data structures by name, and

Oui mais comment ?

Comment travailler avec les classes du package reflect ?

Obtenir un objet java.lang.Class

Récupérer des informations sur la classe

Utiliser l’API de reflect

Illustration à partir de l’exemple

Page 8: Java et la réflexivité. Java reflection is useful because it supports dynamic retrieval of information about classes and data structures by name, and

Classe Class

Les instances de Class représentent les classes et les interfacesd’une application Java. Tous les tableaux sont aussi instances de Class (type des éléments, dimension). Les types primitifs (boolean, byte, char, short, int, long, float, double) et le mot clé void sont aussi des objets Class.

Cette classe n’a pas de constructeur public. Les instances sont créées automatiquement par la VM lorsque les classessont chargées et par la méthode defineClass des class loader.

Page 9: Java et la réflexivité. Java reflection is useful because it supports dynamic retrieval of information about classes and data structures by name, and

Obtenir un objet java.lang.Class

représentant de la classe que l’on veut manipuler : Pour les types fondamentaux Class c = int.class; ou Class c = Integer.TYPE;

TYPE est une variable prédéfinie du wrapper (Integer, par exemple) du type fondamental.

Pour les autres classes

Class c = Class.forName("java.lang.String");

Page 10: Java et la réflexivité. Java reflection is useful because it supports dynamic retrieval of information about classes and data structures by name, and

Récupérer des informations sur la classe

Appeler une méthode sur l’objet classe récupéré :

getDeclaredMethods : pour obtenir la liste de toutes les méthodes déclarées dans la classe

getConstructors : pour obtenir la liste des constructeurs dans la classe

getDeclaredFields : pour obtenir la liste des variables déclarées dans la classe (quelque soit l’accesseur et non héritée)

getFields : pour obtenir la liste des variables publiques accessibles....

Page 11: Java et la réflexivité. Java reflection is useful because it supports dynamic retrieval of information about classes and data structures by name, and

Utiliser l’API de reflect

Par exemple :

Class c = Class.forName("java.lang.String"); Method m[] = c.getDeclaredMethods(); System.out.println(m[0]));

pour manipuler l’information

Page 12: Java et la réflexivité. Java reflection is useful because it supports dynamic retrieval of information about classes and data structures by name, and

Comment Simuler l’opérateur instanceOf

public class instance1 { public static void main(String args[]) {try {Class cls = Class.forName("A"); boolean b1 = cls.isInstance(new Integer(37)); System.out.println(b1); boolean b2 = cls.isInstance(new A()); System.out.println(b2); } catch (Throwable e) {System.err.println(e)} } }

Il existe une Classe A et on veut vérifier si certaines instances sont de cette classe ou pas.

FALSE

TRUE

Page 13: Java et la réflexivité. Java reflection is useful because it supports dynamic retrieval of information about classes and data structures by name, and

classe AccessibleObject et interface Member

AccessibleObject : Classe de base de Field, Method et Constructor. Permet de supprimer ou de valider la vérification faite par défautconcernant les contrôles d’accès. Ces vérifications (sur private, public, package..) sont effectuéeslorsqu’on affecte ou lit des champs, lorsqu’on invoque une méthodeet lorsqu’on crée une instance.

Member : interface qui réifie les informations communes à un membre(champ ou méthode) ou à un constructeur.

Page 14: Java et la réflexivité. Java reflection is useful because it supports dynamic retrieval of information about classes and data structures by name, and

Classes Method, Field et Constructor

Method fournit les informations et les accès à une méthode(de classe, d’instance ou abstraite) d’une classe ou d’une interface.

Field fournit les informations et accès dynamiques aux champs (static ou d’instances) d’une classe ou d’une interface. Constructor fournit des informations et des accès à unconstructeur d’une classe.

Page 15: Java et la réflexivité. Java reflection is useful because it supports dynamic retrieval of information about classes and data structures by name, and

Les méthodes d’une classe ?

1. récupérer l ’objet Class que l’on souhaite observer, 2. récupérer la liste des objets Method par getDeclaredMethods :méthodes définies dans cette classe (public, protected, package, etprivate) getMethods permet d’obtenir aussi les informations concernant les méthodes héritées3. A partir des objets méthodes il est facile de récupérer : les types de paramètres, les types d’exception, et le type de l’argument retourné sous la forme d’un type fondamental ou d’un objet classe.

Page 16: Java et la réflexivité. Java reflection is useful because it supports dynamic retrieval of information about classes and data structures by name, and

Exemple de programme

Class cls = Class.forName("method1"); Method methlist[] = cls.getDeclaredMethods(); for (int i = 0; i < methlist.length; i++) { Method m = methlist[i]; System.out.println("name = " + m.getName()); System.out.println("decl class = " + m.getDeclaringClass()); Class pvec[] = m.getParameterTypes(); for (int j = 0; j < pvec.length; j++) System.out.println("param #" + j + " " + pvec[j]); Class evec[] = m.getExceptionTypes(); for (int j = 0; j < evec.length; j++) System.out.println("exc #" + j + " " + evec[j]); System.out.println("return type = " + m.getReturnType());}

Page 17: Java et la réflexivité. Java reflection is useful because it supports dynamic retrieval of information about classes and data structures by name, and

Exemple d’exécution

name = f1decl class = class method1param #0 class java.lang.Objectparam #1 intexc #0 class java.lang.NullPointerExceptionreturn type = intname = maindecl class = class method1param #0 class java.lang.Stringreturn type = void

public class method1 { private int f1(Object p, int x) throws NullPointerException {……..} public static void main(String args[]) {….}

Page 18: Java et la réflexivité. Java reflection is useful because it supports dynamic retrieval of information about classes and data structures by name, and

Informations sur les constructeurs

Les constructeurs sont similaires aux méthodes

mais ne renvoient pas de résultat

Page 19: Java et la réflexivité. Java reflection is useful because it supports dynamic retrieval of information about classes and data structures by name, and

Découverte des variables

Similaire à la découverte de méthodes et de constructeurs.

l’utilisation de la classe Modifier. Modifier représente les modifiers des variables (private int ...). Ils sont eux mêmes représentés par un integer, Modifier.toString renvoie la chaine correspondant à l’ordre « officiel » ("static" avant "final").

On peut obtenir les informations sur les variables définies dansles super classes par getFields.

Page 20: Java et la réflexivité. Java reflection is useful because it supports dynamic retrieval of information about classes and data structures by name, and

Invocation des méthodes par leur nom

Equivalent du apply de Scheme

pour invoquer une méthode m dont le nom est spécifié à l’exécution(dans le cadre de l’environnement de développement des JavaBeans par exemple)1. Trouver une méthode dans une classe getMethod à partirdes types de ses paramètres et de son nom. 2. La stocker dans un objet Method3. Construire la liste des paramètres d’appel 4. Faire l’appel

Si on manipule un type fondamental à l’appel ou au retour l’encapsuler dans la classe correspondante (int , Integer)

Page 21: Java et la réflexivité. Java reflection is useful because it supports dynamic retrieval of information about classes and data structures by name, and

Exemple de programme

Class cls = Class.forName("method2");Class partypes[] = new Class[2];partypes[0] = Integer.TYPE;partypes[1] = Integer.TYPE;Method meth = cls.getMethod("add",partypes);method2 methobj = new method2();Object arglist[] = new Object[2];arglist[0] = new Integer(37);arglist[1] = new Integer(47);Object retobj = meth.invoke(methobj, arglist); Integer retval = (Integer)retobj;System.out.println(retval.intValue())

Page 22: Java et la réflexivité. Java reflection is useful because it supports dynamic retrieval of information about classes and data structures by name, and

Exemple d’exécution

public class method2 { public int add(int a, int b) { return a + b; } public static void main(String args[]) {…… ……

}

?

Page 23: Java et la réflexivité. Java reflection is useful because it supports dynamic retrieval of information about classes and data structures by name, and

Création de nouveaux objets

Invoquer un constructeur implique de créer un nouvel objet(allouer de la mémoire et construire l’objet)

1. Trouver un constructeur qui accepte les types spécifiés 2. L’invoquer

Création purement dynamique avec recherche (lookup) du constructeuret invocation à l’exécution et non à la compilation.

Page 24: Java et la réflexivité. Java reflection is useful because it supports dynamic retrieval of information about classes and data structures by name, and

Utilisation des tableaux

Création et manipulation des tableaux. Array = un type spécial de classe Le type du tableau qui est créé est dynamique et n’a pas besoind’être connu à la compilation

Page 25: Java et la réflexivité. Java reflection is useful because it supports dynamic retrieval of information about classes and data structures by name, and

Réflexivité = un package Java

java.lang.reflect.*

des classes: Object

AccessibleObject

Constructor

Field

Method Array

InvocationTargetException

Modifier

ReflectPermission

une interface : Member

Page 26: Java et la réflexivité. Java reflection is useful because it supports dynamic retrieval of information about classes and data structures by name, and

Exemples concrets d’applications

En RMI ?Que font les stubs ?Comment peut on utiliser la réflexivité pour les écrire ?

1. Trouver la liste des méthodes Remote2. Du côté client

1. Sérialiser et envoyer sur le réseau2. Attendre le résultat sérialisé et le restructurer

3. Dou côté du serveur1. Déserialiser ce qui est reçu et invoquer la méthode avec les paramètres2. Récupérer le résultat, le sérialiser et l’envoyer au client

Page 27: Java et la réflexivité. Java reflection is useful because it supports dynamic retrieval of information about classes and data structures by name, and

Quelques Informations utiles sur la sérialisation Java

Page 28: Java et la réflexivité. Java reflection is useful because it supports dynamic retrieval of information about classes and data structures by name, and

Sérialisation-Desérialisation

• Enregistrer ou récupérer des objets dans un flux– Persistance– Transfert sur le réseau

Page 29: Java et la réflexivité. Java reflection is useful because it supports dynamic retrieval of information about classes and data structures by name, and

Sérialisation

• Via la méthode writeObject()– Classe implémentant l’interface OutputObject

– Exemple : la classe OutputObjectStream

– Sérialisation d’un objet -> sérialisation de tous les objets contenus par cet objets

• Un objet est sauvé qu’une fois : cache pour les listes circulaires

Page 30: Java et la réflexivité. Java reflection is useful because it supports dynamic retrieval of information about classes and data structures by name, and

Desérialisation

• Via la méthode readObject()– Classe implémentant l’interface InputObject

– Exemple : la classe InputObjectStream

Page 31: Java et la réflexivité. Java reflection is useful because it supports dynamic retrieval of information about classes and data structures by name, and

Exception NotSerializableException

• Si la classe de l’objet sauvé– N’étend ni l’interface Java Serializable– Ni l’interface Java Externalizable

Page 32: Java et la réflexivité. Java reflection is useful because it supports dynamic retrieval of information about classes and data structures by name, and

Interface Serializable

• Ne contient pas de méthode

• -> enregistrement et récupération de toutes les variables d’instances (pas de static)+ informations sur sa classe (nom, version), type

et nom des variables • 2 classes compatibles peuvent être utilisées

•Objet récupéré = une copie de l’objet enregistré

Page 33: Java et la réflexivité. Java reflection is useful because it supports dynamic retrieval of information about classes and data structures by name, and

Gestion de la sérialisation desérialisation

• Implémenter les méthodes • private void writeObject(OutputObjectStream s) throws IOException• private void readObject(OutputInputStream s) throws IOException

• defaultReadObject() et defaultWriteObject() méthodes par défaut

• Ajout d’informations à l’enregistrement, choix de sérialisation

• Seulement pour les champs propres de la classe (héritage géré automatiquement)

Page 34: Java et la réflexivité. Java reflection is useful because it supports dynamic retrieval of information about classes and data structures by name, and

Gestion complète de la sérialisation desérialisation : utiliser

Externalizable• Graphe d’héritage complet

• Implémenter les méthodes • public void writeExternal(ObjectOutput o) throws

IOException• public void readExternal(ObjectInput o) throws

IOException

– ATTENTION PBM de SECURITE

Page 35: Java et la réflexivité. Java reflection is useful because it supports dynamic retrieval of information about classes and data structures by name, and

Un peu plus de réflexivité

Les ClassLoader ????

Page 36: Java et la réflexivité. Java reflection is useful because it supports dynamic retrieval of information about classes and data structures by name, and

Classe ClassLoaderClassLoader est une classe abstraite. Un class loader est un objet responsable du chargement des classes Un nom de classe donné, il peut localiser ou générer les données quiconstituent une définition de la classe. Chaque objet Class a une référence à un ClassLoader qui le définit.

Applications implémentent des sous classes de ClassLoader afind’étendre la façon de dynamiquement charger des classes par la VM.(utilisation de manager de sécurité, par exemple)

Page 37: Java et la réflexivité. Java reflection is useful because it supports dynamic retrieval of information about classes and data structures by name, and

ClassLoader ?

En UNIX la VM charge les classes à partir des chemins définis dans CLASSPATH.

Certaines classes peuvent être obtenues à partir d’autres sources, telles que le réseau ou construites par une application. La méthode defineClass convertit un tableau d’octets en une instance de Class.Instances pouvant être créées grâce à newInstance

Les méthodes et constructeurs créés par un class loader peuvent référencer d’autres classes (loadClass du class loader de cette classe).

Page 38: Java et la réflexivité. Java reflection is useful because it supports dynamic retrieval of information about classes and data structures by name, and

Exemple de chargement de classe

Un class loader qui permet de charger des fichiers de classes via le réseau

ClassLoader loader=new NetworkClassLoader(host,port);Object main= loader.loadClass("Main", true).newInstance();….

NetworkClassLoader doit définir findClass et loadClassData pour charger et defineClass pour créer une instance de Class.

Page 39: Java et la réflexivité. Java reflection is useful because it supports dynamic retrieval of information about classes and data structures by name, and

Utilité et utilisation RMI

Page 40: Java et la réflexivité. Java reflection is useful because it supports dynamic retrieval of information about classes and data structures by name, and

Chargement dynamique des classes

• Problème de sécurité• Le programme client télécharge du code sur le réseau

• Ce code pourrait contenir des virus ou effectuer des opérations non attendues !!!

• Utilisation d ’un gestionnaire de sécurité pour les applications de clients RMI

• Possibilité de créer des gestionnaires de sécurité personnalisés pour des applications spécifiques

• RMI fournit des gestionnaires de sécurité suffisants pour un usage classique

Page 41: Java et la réflexivité. Java reflection is useful because it supports dynamic retrieval of information about classes and data structures by name, and

• Pour ne plus déployer les classes du serveur chez le client

• Utilisation des chargeurs de classes qui téléchargent des classes depuis une URL

• Utilisation d ’un serveur Web qui fournit les classes

• Ce que ça change• Bien entendu, les classes et interfaces de l’ objet distant ne changent pas

• Le code du serveur ne change pas

• le client et la façon de le démarrer sont modifiés

• Et lancer un serveur Web pour nos classes

Chargement dynamique

Page 42: Java et la réflexivité. Java reflection is useful because it supports dynamic retrieval of information about classes and data structures by name, and

• Séparation des classes– Serveur (fichiers nécessaires a l'exécution du serveur)

• HelloWorldServer.class

• HelloWorldImpl.class

• HelloWorld.class

• HelloWorldImpl_Stub.class

– Download (fichiers de classes à charger dans le programme client)• HelloWorldImpl_Stub.class

– Client (fichiers nécessaires au démarrage du client)• HelloWorld.class

• HelloWorldClient.class

Hello World : chargement dynamique

Page 43: Java et la réflexivité. Java reflection is useful because it supports dynamic retrieval of information about classes and data structures by name, and

• Mettre les classes Download dans le répertoire des documents Web du serveur Web, accessibles via une URL

– le chargeur de classes ira chercher les classes à un emplacement de type http://www.class-server.com/classes/HelloWorldImpl_Stub.class

};

Hello World : Démarrage du serveur Web

Page 44: Java et la réflexivité. Java reflection is useful because it supports dynamic retrieval of information about classes and data structures by name, and

– Le programme Java client doit pouvoir se connecter aux ports de la base de registres RMI et des implémentations des objets de serveur, ainsi qu'au port du serveur Web

– Fichier client.policygrant {

permission java.net.SocketPermission"*:1024-65535", "connect,resolve";

permission java.net.SocketPermission"*:80", "connect";

};

Hello World : Politiques de sécurité

Page 45: Java et la réflexivité. Java reflection is useful because it supports dynamic retrieval of information about classes and data structures by name, and

• Le client intègre un gestionnaire de sécurité RMI pour les stubs téléchargés dynamiquementimport java.rmi.*;import java.rmi.server.*;

public class HelloWorldClient {

public static void main(String[] args) {try {

// Installe un gestionnaire de sécurité RMISystem.setSecurityManager(new RMISecurityManager());System.out.println("Recherche de l'objet serveur...");HelloWorld hello = (HelloWorld)Naming.lookup("rmi://server/HelloWorld");System.out.println("Invocation de la méthode sayHello...");String result = hello.sayHello();System.out.println("Affichage du résultat :");System.out.println(result);

} catch(Exception e) {e.printStackTrace();

}}

}

Hello World : gestionnaire de sécurité RMI

Page 46: Java et la réflexivité. Java reflection is useful because it supports dynamic retrieval of information about classes and data structures by name, and

– 1) Lancer la base de registres RMI (elle doit pouvoir accéder aux classes Download - CLASSPATH)> rmiregistry

– 2) Lancer le serveur Web servant les fichiers de classes Download

– 3) Lancer le serveur (les classes Server doivent être accessibles)> java HelloWorldServer

Création de l'objet serveur...Référencement dans le RMIRegistry...Attente d'invocations - CTRL-C pour stopper

Hello World : Démarrage coté serveur

Page 47: Java et la réflexivité. Java reflection is useful because it supports dynamic retrieval of information about classes and data structures by name, and

– Le client doit pouvoir se connecter à des machines distantes pour la base de registres RMI, les objets de serveur ainsi que le serveur Web

• On doit lui fournir un fichier client.policy

– Le client doit bien connaître l'emplacement des classes afin de pouvoir les télécharger

• On va le lui préciser lors du lancement

> java -Djava.security.policy=client.policy -Djava.rmi.server.codebase=http://www.class-server.com:80/ HelloWorldClient

Hello World : Démarrage coté client