Programmation avance et rpartie en Java : lacl.univ- avanc ee et r epartie en Java : Programmation dynamique et r ef erences faibles Fr ed eric Gava L.A.C.L Laboratoire d’Algorithmique,

  • View
    218

  • Download
    4

Embed Size (px)

Text of Programmation avance et rpartie en Java : lacl.univ- avanc ee et r epartie en Java : Programmation...

  • Programmation avancee et repartie en Java :Programmation dynamique et references faibles

    Frederic Gava

    L.A.C.LLaboratoire dAlgorithmique, Complexite et Logique

    Cours de M1 MIAGE(dapres les notes de cours de Fabrice Mourlin)

  • Plan

    1 Programmation dynamique

    2 Class Loader

    3 References faibles

  • Plan

    1 Programmation dynamique

    2 Class Loader

    3 References faibles

  • Plan

    1 Programmation dynamique

    2 Class Loader

    3 References faibles

  • Programmation dynamiqueClass Loader

    References faibles

    Deroulement du cours

    1 Programmation dynamique

    2 Class Loader

    3 References faibles

    Programmation avancee et repartie en Java 3 / 48

  • Programmation dynamiqueClass Loader

    References faibles

    Quest-ce ?

    La classe Class et le package java.lang.reflect sont les bases de laprogrammation dynamique.

    Problemematique

    La decouverte et lutilisation au runtime dobjets dun typeinconnu. La definition de protocoles auquels doivent adherer cesobjets inconnus (convention de Bean) permet de creer des outilscapables de manipuler dynamiquement des categories dobjets.

    Le compilateur

    Java etant un langage compile puis interprete (JVM), les codesque lon ecrit operent sur des classes connues au compile-time. Ilest pourtant possible decrire des programmes qui operent sur desclasses inconnues du compilateur.

    Programmation avancee et repartie en Java 4 / 48

  • Programmation dynamiqueClass Loader

    References faibles

    Pourquoi ?

    Du fait du polymorphisme, des operations definies par destypes connus du compilateur (classes ou interfaces) peuventen realite operer sur des objets ayant un type effectif nonapparent ; les classes correspondantes peuvent meme avoir etedecouvertes et chargees dynamiquement a lexecution.

    Il peut saverer utile de decouvrir lAPI dune classe alexecution et de pouvoir lutiliser. Cest en particulier le casde certains outils Java : generation de protocoles (comme lalinearisation des objets), outils de deploiement, assemblagesinteractifs de composants, composants graphiques generiquessadaptant a des modeles predefinis, etc.

    Programmation avancee et repartie en Java 5 / 48

  • Programmation dynamiqueClass Loader

    References faibles

    Vocabulaire

    Reflexion : se connaitre soi meme. Les 3 niveaux de reflexion :

    Classe des objets lors de lexecution, cast avec exception,instanceof

    Introspection ; ensemble des methodes, champs, classesinternes, appel dynamique, modification, bypass la securite

    Intercession, changer la facon deffectuer lappel de methode,ajouter des champs, emuler en Java par modification dubyte-code (prog par aspect, java.lang.instrument)

    Programmation avancee et repartie en Java 6 / 48

  • Programmation dynamiqueClass Loader

    References faibles

    La classe des classes

    Pour pouvoir operer a un niveau interpretatif sur un objet on abesoin dune instance de la classe java.lang.Class representant laclasse de lobjet. Une telle instance peut sobtenir par :

    Chargement dynamique dune classe au travers dunClassLoader ; on doit alors fournir une chane donnant le nomcomplet de la classe (hierarchie de package + nom de classe) :Class laClasse = Class.forName(nom);

    Obtention de la classe dune instance (p. ex. un transfertdistant) : Class laClasse = instance.getClass();Consultation dun champ statique connu au compile-time :Class PanelClass = JPanel.class;Class tabCharClass = char[].class;Class typeInt = int.class;Class typeInt = Integer.TYPE;

    cas particulier des scalaires primitifs : on ne peut pas faire desoperations objet avec. Mais (voir plus tard)...

    Programmation avancee et repartie en Java 7 / 48

  • Programmation dynamiqueClass Loader

    References faibles

    Obtention dinformations

    A partir dune instance de Class (qui ne repond pas a la conditionisPrimitive()) on peut obtenir des informations sur lesconstituants :

    Quels sont les champs declares dans la classe ?Field[] champs = maClasse.getDeclaredFields();

    si la classe represente une tableau (isArray() repond true), ilest possible de connatre le type des composants :

    Class typeComposants = classeTableau.getComponentType();

    Quelles sont les methodes definies dans la classe ?Method[] methodes = maClasse.getDeclaredMethods();

    Quels sont les constructeurs definis dans la classe ?Constructor[] constructeurs=maClasse.getDeclaredConstructors();

    Lutilisation des classes correspondantes (Field, Method,Constructor, etc.) releve du package java.lang.reflect.

    Programmation avancee et repartie en Java 8 / 48

  • Programmation dynamiqueClass Loader

    References faibles

    Class et type parametreUn objet de type Class est parametre par le type representeClass clazz=String.class;String s=clazz.newInstance();

    Pour getClass(), a cause du sous-typage, la regle estClass clazz=Class.forName(args[0]);Object obj=clazz.newInstance();for(Field field:clazz.getFields()){System.out.println(=>field +field.getName()+ +field.get(obj));}

    //gava@gavalaptop:$ java reflect.GetFields java.awt.Point// =>field x 0// =>field y 0

    Programmation avancee et repartie en Java 9 / 48

  • Programmation dynamiqueClass Loader

    References faibles

    Pour les types primitifs

    les types primitifs (int, void, etc.) ont des objets Classcorrespondants.type primitif.class est type Class et pour void,void.class est type Class

    public static void main(String[] args) throws ... {Class clazz=Integer.class;Class clazz2=int.class;Integer i=clazz.getConstructor(clazz2).newInstance(3);}

    On voit bien que new nest quun raccourci pour la methodenewInstance()

    Programmation avancee et repartie en Java 10 / 48

  • Programmation dynamiqueClass Loader

    References faibles

    Codes reflexifs

    La manipulation des champs, methodes, constructeurs peut poserdes problemes de droit dacces. Pourtant certains mecanismesdoivent pouvoir agir independament des privileges de responsabilite(private, protected, etc.) :

    Membres et constructeurs de la classe derivent tous dejava.lang.reflect.AccessibleObject qui dispose dune methodesetAccessible(boolean) qui permet de passer outre auxprivileges de responsabilite.

    Bien entendu nimporte quel code ne peut realiser cesoperations sans disposer dune autorisation de securiteadequate : java.lang.reflect.ReflectPermission(suppressAccessChecks)

    Programmation avancee et repartie en Java 11 / 48

  • Programmation dynamiqueClass Loader

    References faibles

    Codes reflexifs : les champs

    A partir dune instance de Field on peut obtenir :

    son nom : String nom = champs[ix].getName();

    son type : Class type = champs[ix].getType();

    dautres informations comme les modificateurs utilises.On peut egalement consulter la valeur de ce membre (ou lamodifier). Les assesseurs get/setXXX permettent de lire oumodifier une valeur sur une instance passee en parametre :

    Class laClasse = instance.getClass() ;Field leChamp0 = laClasse.getDeclaredFields() [0];.... // obtention informations de type.... // fixation evt. des droits dacces.....// creation dun objet de ce type: valeurObjetleChamp0.set(instance, valeurObjet);

    Si champ statique, le premier argument est ignore (peut etre null).

    Programmation avancee et repartie en Java 12 / 48

  • Programmation dynamiqueClass Loader

    References faibles

    Propriete de la class Class

    Savoir si la classe est :

    une annotation isAnnotation()

    une classe anonyme isAnonymousClass()

    Un tableau isArray()

    Un type enumere isEnum()

    Une interface isInterface()

    Une classe locale a une methode isLocalClass()

    Une classe interne isMemberClass()

    Une classe dun type primitif isPrimitive()

    Generee par le compilateur isSynthetic()

    Programmation avancee et repartie en Java 13 / 48

  • Programmation dynamiqueClass Loader

    References faibles

    Hierarchie de classes

    Il est possible pour une classe dobtenir :

    sa superclass Class[] getInterfaces()

    De plus, on peut :

    Tester si un objet est de cette classe isInstance(Object o)

    Tester si une classe est sous-type dune autreisAssignableFrom(Class clazz)

    Caster une reference vers la classe T cast(Object o)

    Voir this comme une sous-classe du parametre Class

  • Programmation dynamiqueClass Loader

    References faibles

    Typesafe generics

    cast() et asSubclass() sont utilise pour verifier a runtime des castsnon verifiables a cause de lerasure

    public static T createNullProxy(Class interfaze) {Object o=Proxy.newProxyInstance(interfaze.getClassLoader(),

    new Class[]{ interfaze },EMPTY HANDLER);//return (T)o; // unsafereturn interfaze.cast(o); // ok safe}

    public static Class lafClass=Class.forName(className);//return (Class

  • Programmation dynamiqueClass Loader

    References faibles

    Creer un objet a partir de sa Class

    La classe Class possede une methode newInstance() quirenvoie un objet de type T

    public static void main(String[] args) throws ... {Class clazz=String.class;String s=clazz.newInstance();...

    Leve les exceptions suivantes :

    InstantiationException, si la classe est abstraite ou quilnexiste pas de constructeur sans parametreIllegalAccessException, si le constructeur nest pas publiqueInvocationTargetException, si une exception est levee par leconstructeur, celle-ci est stockee dans la cause de lexception

    Programmation avancee et repartie en Java 16 / 48

  • Programmation dynamiqueClass Loader

    References faibles

    java.lang.reflect