Télécharger la présentation
La présentation est en train de télécharger. S'il vous plaît, attendez
1
Approfondissement du Java
X. BLANC & J. DANIEL ,
2
Plan du cours Compléments sur la langage Java L'API Reflexion
Le chargement de classes La sécurité dans Java Les interfaces natives
3
Compléments sur la langage Java
Approfondissement de Java X.BLANC & J. DANIEL
4
Commenter ses programmes Java
Pour commenter les programmes Java, on peut utiliser le système « javadoc » qui permet par la suite la génération automatique de documentations. Format d'un commentaire « javadoc » : /** * Placer ici le commentaire JavaDoc */ Le début du commentaire est obligatoirement /**
5
Les « tags » de JavaDoc Les « tags » identifient des sections afin de structurer le commentaire. Les « tags » disponibles sont : author version param return exception see deprecated Chaque « tag » respecte la syntaxe suivante : @tag valeur
6
Génération des documentations
L'utilitaire « javadoc » permet de générer les documentations. javadoc [ options ] fichiers sources La génération des documentations peut être personnalisée à l'aide de « doclet ». mise à disposition d'une API permettant de récupérer les informations de commentaires, utilisation de l'option « -doclet »
7
Les attentes de signaux
L'instruction « wait » bloque le thread courant. public void wait(); public void wait( long timeout ); L'instruction « notify » débloque un thread en attente. public void notify(); L'instruction « notifyAll » débloque tous les threads qui sont en attentes. public void notifyAll(); L'objet sur lequel s'applique ces opérations d'attentes est appelé un moniteur.
8
Utilisation des moniteurs
Utilisez la notion de moniteur pour développer des opérations substituants « suspend » et « resume ».
9
Le clonage Le clonage permet la copie d'un objet java.
Pour pouvoir être cloné, un objet doit implanter l'interface « java.lang.Cloneable ». La méthode « clone » de la classe objet permet le clonage d'un objet champs par champs. Les champs statiques ne sont pas clonés. Si un objet clonable contient un autre objet clonable, celui-ci ne sera pas automatiquement cloné.
10
Gestion des processus Avec Java, on peut gérer les processus :
création et exécution de processus, arrêt de processus Deux classes importantes sont à utiliser : java.lang.Runtime java.lang.Process On récupère le Runtime via l'opération statique « getRuntime » de l'interface Runtime : static public Runtime getRuntime();
11
La classe « java.lang.Runtime »
Cette classe permet entre autre d'obtenir des informations sur l'environnement d'exécution : mémoire disponible : freeMemory mémoire totale : totalMemory On peut également créer de nouveau processus : Process exec( String command ) throws IOException Process exec( String command, String [] envp )
12
La classe « java.lang.Process »
La classe Process symbolise un processus. Les opérations disponibles sont : void destroy() : supprime le processus int waitFor() : suspend l'exécution du thread courant jusqu'à la fin de ce processus ( avec exception possible : IllegalThreadStateException ) int exitStatus(): retourne le code d'arrêt du processus On peut aussi accéder aux flux d'entrées et de sorties du processus : InputStream getInputStream( ) OutputStream getOutputStream( ) InputStream getErrorStream( )
13
Utilisation des processus
Mettre en place une application qui exécute trois processus fils ou chaque fils effectue une simple attente de 10 secondes. Si au bout de 30 secondes, les processus fils ne sont pas terminés, le père doit tuer tous ses fils encore vivants.
14
Approfondissement de Java X.BLANC & J. DANIEL
L'API Reflexion Approfondissement de Java X.BLANC & J. DANIEL
15
Une API réflexive ! Java permet d'obtenir des informations de descriptions sur les classes, les opérations, les types, etc….. Grâce à la réflexion, on peut analyser dynamiquement un classe, mais également l'utiliser. Offre une grande souplesse d'utilisation des applications java telle que la mobilité du code.
16
Obtenir la description d'une classe Java
Une classe est symbolisée par la classe « java.lang.Class » Chaque instance de classe peut retourner un descripteur de sa classe par l'intermédiaire de l'opération « getClass » maClasse m = new maClasse(); java.lang.Class cl = m.getClass(); Chaque classe comporte également un attribut appelé « class » pour récupérer sa description : java.lang.Class cl = maClass.class;
17
Obtention dynamique d'une description !
A partir du nom d'une classe, on peut récupérer dynamiquement sa description en utilisant l'opération statique « forName » : java.lang.Class cl = java.lang.Class.forName("exemple.maClasse"); Attention, cette opération retourne l'exception « ClassNotFoundException »
18
La classe « java.lang.Class »
La classe « Class » retourne toutes les informations permettant de connaître la description d'une classe : son nom ( getName ), son package ( getPackage ) , ses constructeurs ( getConstructors ), ses méthodes ( getMethods ), ses attributs ( getFields ), son ancêtre ( getSuperclass ) , les interfaces qu'elle implante ( getInterfaces ).
19
Description d'un Package
La description d'un package est offert par la classe « java.lang.Package » au moyen de l'opération « getPackage » java.lang.Package getPackage(); Cette classe propose les opérations suivantes : String getName() : retourne le nom du package Package getPackage() : retourne le package de ce package Package [] getPackages() : retourne la liste des packages de ce package.
20
Description des constructeurs
Pour décrire un constructeur, on utilise classe « java.lang.reflect.Constructor ». Les descriptions de constructeurs sont retournés par « getConstructors » : java.lang.reflect.Constructor [ ] getConstructors(); Les opérations de « java.lang.reflect.Constructor » sont : String getName() : retourne le nom du constructeur int getModifiers() : retourne les modificateurs qui s'appliquent au constructeur java.lang.Class getExceptionType() : retourne les descriptions des exceptions lancées par le constructeur
21
Les modificateurs La classe « java.lang.reflect.Modifier » permet la manipulation des modificateurs retournés par les descriptions. Cette classe propose un ensemble d'opérations permettant de tester la validité d'un modificateur ( final, abstract, public, private, protected, static, transient, synchronized ). Ces opérations respectent la syntaxe suivante : public static boolean isXXXXX( int modifier )
22
Description des méthodes
Afin de décrire une méthode, la classe « java.lang.reflect.Method » est utilisée. Les descriptions de méthodes sont retournées par « getMethods » java.lang.reflect.Method [ ] getMethods( ); Les principales opérations de cette classe sont : String getName() : retourne le nom de la méthode int getModifier() : retourne les modificateurs de la méthodes Class [] getExceptionType() : la liste des exceptions Class [] getParamType() : la liste des paramètres Class getReturnType() : retourne le type de retour de la méthode
23
Description des attributs
Pour décrire un attribut, la classe « java.lang.reflect.Field » est utilisée. Java.lang.reflect.Field [ ] getFields(); Les principales opérations sont : String getName() : nom de l'attribut int getModifier() : modificateur de l'attribut Class getType() : type de l'attribut Pour savoir, si un type est un type « primitif », on utilise l'opération « isPrimitive ».
24
Description des interfaces
Afin de décrire une interface, on emploi la classe « java.lang.Class » ! java.lang.Class [ ] getInterfaces(); Pour savoir si une classe « Class » décrie une interface, on utilise l'opération « isInterface ».
25
Description des tableaux
Une classe « Class » peut décrire un tableau. Pour savoir, si c'est un tableau on utilise l'opération « isArray » Pour connaître le type du tableau, on emploi l'opération « getComponentType » if ( cl.isArray() ) { java.lang.Class type = cl.getComponentType(); }
26
Création dynamique d'une instance de classe !
On peut créer dynamiquement une instance de classe à l'aide de l'opération « newInstance » : try { java.lang.Class clz = java.lang.Class.forName("maClasse"); java.lang.Object obj = clz.newInstance(); maClasse maC = ( maClasse ) obj; } catch ( java.lang.Exception ex ) ex.printStackTrace( ); La classe à instancier doit impérativement comporter un constructeur sans paramètre.
27
Utilisation dynamique de constructeurs
Si une classe comporte un constructeur avec paramètres, on doit utiliser l'opération « newInstance » de la classe « Constructor » afin d'en créer une instance : java.lang.Object newInstance ( java.lang.Object [ ] params )
28
Utilisation dynamique d'une classe !
L'API reflexion permet une utilisation dynamique des classes : auto-description, instanciation à la demande. Il est impératif de pouvoir effectuer des invocations dynamiques sans utiliser directement le type de la classe cible. java.lang.Class clz = java.lang.Class.forName("maClasse"); java.lang.Object obj = clz.newInstance(); maClasse maC = ( maClasse ) obj;
29
Appel dynamique d'une opération
Pour appeler dynamiquement une opération, on emploi « invoke » : java.lang.Object invoke ( java.lang.Object cible, java.lang.Object [] params ) Si une exception se produit lors de l'invocation, l'opération « invoke » génère l'exception « java.lang.reflect.InvocationTargetException » Parmi les opérations de cette exception, on a : void printStackTrace() Throwable getTargetException()
30
Utilisation dynamique d'un attribut
La classe « Field » comporte plusieurs opérations permettant l'accès aux valeurs des attributs. Ainsi, les opérations suivantes sont définies pour les types primitifs : void setXXXX( java.lang.Object cible, XXXXX value ); XXXX getXXXX( java.lang.Object cible ); Pour les types complexes on a: void set( java.lang.Object cible, java.lang.Object value ); java.lang.Object get( java.lang.Object cible );
31
Mise à l'épreuve... Développez une méthode qui décrie une classe :
affiche ses constructeurs affiche ses méthodes affiche ses attributs.
32
Le chargement de classes
Approfondissement de Java X.BLANC & J. DANIEL
33
Notion de « ClassLoader »
Pour charger les classes, la machine virtuelle utilise un « ClassLoader ». L'utilisateur peut définir son propre chargeur de classes en surchargeant le chargeur standard. La classe « java.lang.ClassLoader » symbolise le chargeur de classes. Pour connaître le chargeur d'une classe, on emploi la méthode « getClassLoader » de la classe « Class » La méthode « getClassLoader » renvoie NULL avec le JDK 1.1.x si le chargeur utilisé n'est pas un chargeur utilisateur.
34
Le chargeur système La machine virtuelle permet de récupérer une référence vers le chargeur du système. Pour cela, on utilise la méthode statique « getSystemClassLoader » de la classe « ClassLoader » : public static java.lang.ClassLoader getSystemClassLoader(); Cette méthode peut éventuellement renvoyer NULL !
35
Fonctionnement d'un chargeur de classe
Classe Java Application Java Classe Java Classe Java Classe Java Chargement des classes constituant l'application Chargement direct Chargeur Chargeur système Délégation du chargement JVM Classe Java
36
Ecrire un chargeur de classe !
Pour écrire son propre chargeur de classe on doit : hériter de la classe « java.lang.ClassLoader » Surcharger la méthode « findClass » public java.lang.Class findClass( String name ); Enfin, la méthode « findClass » doit : récupérer le code correspondant à la classe, définir une classe ( passage du byte code à la classe ). Pour ce faire, on utilise la méthode « defineClass » : protected final java.lang.Class defineClass( String name, byte [] b, int off, int len ); La méthode « defineClass » ne doit jamais être appelée deux fois pour la même classe.
37
Remarque sur le chargeur
Lorsqu'une classe est chargée à partir d'un chargeur utilisateur, toutes les classes qu'elle utilise seront chargées par ce même chargeur. Si le système demande le chargement de deux fois la même classe, on peut vérifier que cela n'a pas été déjà fait par : protected final java.lang.Class findLoadedClass( String name ); Pour pouvoir utiliser une classe chargée, on doit la résoudre : protected final void resolveClass( java.lang.Class class );
38
La classe « URLClassLoader »
Le JDK 1.2 propose un chargeur standard symbolisé par la classe « java.net.URLClassLoader » pour charger des classes à partir de sites spécifiés via des URLs. URLClassLoader( String [ ] URLs ); Parmi les méthodes les plus utilisées de cette classe, on distingue : void addURL( String ) static URLClassLoader newInstance( String [] URLs ) Pour déclencher le chargement d'une classe, on doit pour tous les chargeurs appeler la méthode « loadClass » public java.lang.Class loadClass( String name ) throws ClassNotFoundException;
39
A vous... Ecrire son propre chargeur de classes en récupérant depuis un fichier de propriétés le nom du répertoire où se trouvent les fichiers sources.
40
Approfondissement de Java X.BLANC & J. DANIEL
La sécurité dans Java Approfondissement de Java X.BLANC & J. DANIEL
41
La sécurité dans Java Les objectifs de la sécurité sont :
Fournir un environnement Java sécurisé de telle sorte que les exécutions des applications java s’effectuent d’une manière sécurisée. Fournir un ensemble de mécanismes pour une utilisation à grande échelle permettant un contrôle de la sécurité.
42
Ressources ( fichiers, imprimantes, etc… )
Le modèle du JDK 1.0 Le modèle de sécurité du JDK 1.0 est connu sous le nom de « sandbox » Code distant Code local sandbox J V M Ressources ( fichiers, imprimantes, etc… ) Accès très restreint pour le code distant ( Applet )
43
Ressources ( fichiers, imprimantes, etc… )
Le modèle du JDK 1.1 Le JDK 1.1 introduit la notion « d’applet signée » qui est l ’association d ’un code distant ( Applet ) avec une signature. Code distant signé Code distant Code local sandbox J V M Ressources ( fichiers, imprimantes, etc… ) Le code signé est utilisé comme un code local : trusted
44
Ressources ( fichiers, imprimantes, etc… )
Le modèle du JDK 1.2 Dans le JDK 1.2, les applications s’exécutent selon des règles ( policy ) énumérés extérieurement. Code local ou distant ( signé ou pas ) Règles loader sandbox J V M Ressources ( fichiers, imprimantes, etc… ) Une gestion très fine de la sécurité.
45
Classes, Domaines et Permissions
Une permission est un droit d’accès également appelé privilège. Un domaine est une entité soumis à plusieurs permissions. Un domaine regroupe plusieurs classes. Chaque classe du domaine profite alors des permissions de ce domaine. Domaines des applications Domaines systèmes
46
Gestion des permissions
Une classe de permission permet d’avoir accès à une ressource du système. La classe « java.security.Permission » correspond à la classe de base de toutes les permissions Java. Les permissions peuvent également être manipulées sous forme d’un ensemble ( de permissions hétérogènes ) en utilisant la classe « java.security.Permissions »
47
Quelques types de permissions
Permissions pour accéder à un fichier java.io.FilePermission Permissions pour utiliser les sockets java.net.SocketPermission Permissions pour utiliser les propriétés java.util.PropertyPermission Permissions pour utiliser le Runtime java.lang.RuntimePermission Permissions sur l’API reflexion java.lang.reflect.ReflectPermission Permissions sur la sécurité java.security.SecurityPermission
48
Les permissions sur les fichiers
La classe « java.io.FilePermission » accorde les droits suivants : lecture : read écriture : write suppression :delete exécution : execute Création d'une permission pour les fichiers : java.io.FilePermission( chemin , droits ) Exemple : java.io.FilePermission perm = new java.io.FilePermission("/tmp/*", "read, write");
49
Contrôle d’accès Pour gérer les permission, on utilise un contrôleur d'accès symbolisé par la classe « java.security.AccessController » Pour vérifier une permission, on utilise l'opération « checkPermission » java.io.FilePermission perm = … AccessController.checkPermission( perm ); On peut aussi exécuter une opération selon un privilège spéciale. On appel une telle opération : une action privilégiée.
50
Les actions privilégiées
Une action privilégiée est un ensemble de code implantant l'interface « java.security.PrivilegedAction » interface PrivilegedAction { Object run( ); } Pour lancer une action privilégiée, on utilise l'opération « doPrivilege » du contrôleur d'accès Object doPrivileged( PrivilegedAction action )
51
Le gestionnaire de sécurité
Un environnement Java est lié à un gestionnaire de sécurité symbolisé par la classe « java.lang.SecurityManager ». Le gestionnaire de sécurité utilise un contrôleur d'accès, ce qui permet de vérifier la validité d'une permission. ClassLoader loader = this.getClass().getClassLoader(); if (loader != null) { SecurityManager security = System.getSecurityManager(); if (security != null) { security.checkRead("path/file"); } } On peut surcharger le gestionnaire de sécurité pour fournir sa propre gestion de la sécurité.
52
Les fichiers de permissions
On peut à l ’aide d ’un fichier de « policy » énumérer plusieurs permissions : grant [ SignedBy xxxx ] { permission permission_class_name [ options ] ; // autres permissions... } Exemple : grant permission java.io.FilePermission "/tmp/*", "read, write";
53
Chargement sécurisé de classes
En définissant ses propres chargeurs de classes, l’utilisateur peut violer la sécurité de l’environnement. On peut pour résoudre ce problème, hériter de la classe « java.security.SecureClassLoader » pour définir ses propres chargeurs. Utilisation des permissions, Plus grandes libertés dans le cas d’Applet
54
Epilogue sur la sécurité
Spécification de paramètres de sécurité depuis la ligne de commande : java.security.manager java.security.policy Le JDK 1.2 augmente considérablement la gestion de la sécurité dans Java. Mais certains travaux restent à mettre en place comme la gestion de l'identité et de l'authentification.
55
Les interfaces natives
Approfondissement de Java X.BLANC & J. DANIEL
56
Utiliser depuis Java un code non Java !
Pour des besoins spécifiques, il est parfois indispensable d'ajouter des éléments natifs aux diverses classes Java. Par exemple, on peut sous Windows imaginer une classe qui permette de récupérer la valeur d'une variable de l'environnement Windows. Pour cela, on doit faire appel à des méthodes natives. Plusieurs interfaces natives ont été définies pour pouvoir utiliser depuis Java du code non Java.
57
Signaler qu'une méthode est native
Pour indiquer depuis Java qu'une méthode est native, on doit tout de même la déclarer et utiliser le modificateur « native ». Exemple : public native void printMessage( String message ); On doit également demander à Java de charger la librairie qui contient le code de cette méthode native. On utilise pour cela l'opération « loadLibrary » de la classe « System ». static { System.loadLibrary("Exemple"); } La librairie est une librairie partagée ( DLL sous Windows ) qui doit être placée dans un répertoire accessible depuis le PATH
58
JNI : Java Native Interface
JNI à été ajoutée au JDK 1.1 pour permettre l'appel de méthode native depuis Java. L'utilitaire « javah -jni xxxx » permet la conception d'un header C pour la définition du code natif. JNI fournie une API permettant de mettre en place un wrapper pour interagir entre le C et les différents types et objets de Java.
59
Les difficultés de JNI On doit tout d'abord utiliser l'API de JNI pour accéder à tous les éléments d'un objet Java. L'écriture d'une application complexe vient tout de suite très laborieuse à mettre en place. Se méfier des accès concurrents dues à plusieurs threads Java. Interactions complexes avec le garbage collector !
60
J/Direct J/Direct est une interface native proposée par Microsoft, qui permet un accès facile aux opérations de l'API Win 32. On peut également utiliser J/Direct pour appeler des opérations depuis d'autres DLL. Ce mécanisme est plus lent que JNI ou RNI mais s'avère très simple à mettre en œuvre et ne requiert pas d'adaptation (wrapper) entre les deux environnements.
61
Utilisation de J/Direct
Dans J/Direct, on utilise un commentaire Javadoc spécial pour importer une librairie ( DLL ) /** */ private native void printMessage(String text ); @dll.import peut également s'appliquer à toute une classe en faisant précéder la déclaration de celle-ci par le commentaire adéquat.
62
RNI ( Raw Native Interface )
RNI est également une extension apportée par Microsoft pour effectuer des appels natifs mais cette fois-ci, c'est au développeur de l'interface de gérer la phase de garbage collection. RNI s'utilise sur le même principe que JNI et fournie essentiellement les même possibilités. Par exemple, on doit utiliser « msjavah » à la place de « javah » . Dans RNI, on a directement accès à la représentation binaire de l'objet ce qui permet de manipuler directement les champs de celui-ci. Le format binaire d'un objet n'est pas forcément le même d'une machine virtuelle à l'autre...
Présentations similaires
© 2024 SlidePlayer.fr Inc.
All rights reserved.