Télécharger la présentation
1
Java et la réflexivité
2
Java reflection is useful because it supports dynamic retrieval
of 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.
3
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 Eclipse L’outil utilise la réflexivité pour obtenir liste des méthodes publiques qui peuvent être envoyées à une instance d’une classe
4
Que peut on faire ? Obtenir des informations sur les classes
Simuler l’opérateur instanceof Découvrir la liste et le descriptif des méthodes Obtenir des informations sur les constructeurs Avoir des informations sur les variables Invoquer des méthodes, des constructeurs, affecter des variables Créer des objets et des tableaux dynamiquement lors de l ’exécution du programme sans 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….
5
Réflexivité = un package Java
java.lang.reflect.* des classes: Object AccessibleObject Modifier ReflectPermission Constructor InvocationTargetException Field Array Method une interface : Member
6
Un exemple simple public 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);} java.util.Stack 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)
7
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
8
Classe Class Les instances de Class représentent les classes et les interfaces d’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 classes sont chargées et par la méthode defineClass des class loader.
9
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");
10
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 ....
11
Utiliser l’API de reflect
pour manipuler l’information Par exemple : Class c = Class.forName("java.lang.String"); Method m[] = c.getDeclaredMethods(); System.out.println(m[0]));
12
Comment Simuler l’opérateur instanceOf
Il existe une Classe A et on veut vérifier si certaines instances sont de cette classe ou pas. 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)} FALSE TRUE
13
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éfaut concernant les contrôles d’accès. Ces vérifications (sur private, public, package..) sont effectuées lorsqu’on affecte ou lit des champs, lorsqu’on invoque une méthode et lorsqu’on crée une instance. Member : interface qui réifie les informations communes à un membre (champ ou méthode) ou à un constructeur.
14
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 à un constructeur d’une classe.
15
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, et private) getMethods permet d’obtenir aussi les informations concernant les méthodes héritées 3. 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.
16
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());}
17
Exemple d’exécution public class method1 {
private int f1(Object p, int x) throws NullPointerException {……..} public static void main(String args[]) {….} name = f1 decl class = class method1 param #0 class java.lang.Object param #1 int exc #0 class java.lang.NullPointerException return type = int name = main param #0 class java.lang.String return type = void
18
Informations sur les constructeurs
Les constructeurs sont similaires aux méthodes mais ne renvoient pas de résultat
19
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 dans les super classes par getFields.
20
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 à partir des types de ses paramètres et de son nom. 2. La stocker dans un objet Method 3. 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)
21
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())
22
Exemple d’exécution public class method2 {
public int add(int a, int b) { return a + b; } public static void main(String args[]) {…… …… ?
23
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 constructeur et invocation à l’exécution et non à la compilation.
24
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 besoin d’être connu à la compilation
25
Réflexivité = un package Java
java.lang.reflect.* des classes: Object AccessibleObject Modifier ReflectPermission Constructor InvocationTargetException Field Array Method une interface : Member
26
Exemples concrets d’applications
En RMI ? Que font les stubs ? Comment peut on utiliser la réflexivité pour les écrire ? Trouver la liste des méthodes Remote Du côté client Sérialiser et envoyer sur le réseau Attendre le résultat sérialisé et le restructurer Dou côté du serveur Déserialiser ce qui est reçu et invoquer la méthode avec les paramètres Récupérer le résultat, le sérialiser et l’envoyer au client
27
Quelques Informations utiles sur la sérialisation Java
28
Sérialisation-Desérialisation
Enregistrer ou récupérer des objets dans un flux Persistance Transfert sur le réseau
29
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
30
Desérialisation Via la méthode readObject()
Classe implémentant l’interface InputObject Exemple : la classe InputObjectStream
31
Exception NotSerializableException
Si la classe de l’objet sauvé N’étend ni l’interface Java Serializable Ni l’interface Java Externalizable
32
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é
33
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)
34
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
35
Un peu plus de réflexivité
Les ClassLoader ????
36
Classe ClassLoader ClassLoader 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 qui constituent 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 afin d’étendre la façon de dynamiquement charger des classes par la VM. (utilisation de manager de sécurité, par exemple)
37
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).
38
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.
39
Utilité et utilisation RMI
40
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
41
Chargement dynamique 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
42
Hello World : chargement dynamique
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) Client (fichiers nécessaires au démarrage du client) HelloWorldClient.class
43
Hello World : Démarrage du serveur Web
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 };
44
Hello World : Politiques de sécurité
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.policy grant { permission java.net.SocketPermission "*: ", "connect,resolve"; "*:80", "connect"; };
45
Hello World : gestionnaire de sécurité RMI
Le client intègre un gestionnaire de sécurité RMI pour les stubs téléchargés dynamiquement import java.rmi.*; import java.rmi.server.*; public class HelloWorldClient { public static void main(String[] args) { try { // Installe un gestionnaire de sécurité RMI System.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(); }
46
Hello World : Démarrage coté serveur
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
47
Hello World : Démarrage coté client
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= HelloWorldClient
Présentations similaires
© 2024 SlidePlayer.fr Inc.
All rights reserved.