IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Langage Java Discussion :

API Reflection et sécurité


Sujet :

Langage Java

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre habitué
    Inscrit en
    Février 2006
    Messages
    12
    Détails du profil
    Informations forums :
    Inscription : Février 2006
    Messages : 12
    Par défaut API Reflection et sécurité
    Bonjour à tous,

    J'utilise un Iterator sur un Set ramené par Map.entrySet.
    Pour rappel cette méthode renvoie un Set<Map.Entry>

    J'aimerais comprendre la différence suivante:
    - dans un code standard, je peux faire Map.entrySet.getKey()
    - avec l'API de reflection, sur une instance de HashMap, l'appel à la méthode getKey lance une IllegalAccessException !

    En y regardant de plus près, on voit que Map.Entry (et getKey) a un niveau package, alors que HashMap.Entry (qui hérite de Map.Entry) a un niveau package aussi mais que getKey est public.
    En toute logique, Map.entry.getKey ne devrait pas être accessible de l'extérieur du package tandis que HashMap.entry.getKey devrait l'être. Hors il semble que ce soit l'inverse qui soit possible !

    (je suis en Java 1.5)

    Si quelqu'un peut me dire où je me plante, je serais content de comprendre...

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
     
    	public static void main(String[] args) throws Throwable {
    		// récupération de la méthode getKey
    		Method mapGetKey = Map.Entry.class.getDeclaredMethod("getKey");
    		// récupération d'une instance de HashMap.entry pour pouvoir faire un getKey
    		// NB: je ne peux pas avoir directement HashMap.Entry.class car elle est niveau package
    		HashMap<String, String> hm = new HashMap();
    		hm.put("a", "b");
    		Map.Entry entry = (Entry) hm.entrySet().iterator().next();
    		Method hashMapGetKey = entry.getClass().getDeclaredMethod("getKey");
     
    		// je vais récupérer a-b
    		//System.out.println(hashMapGetKey.invoke(entry));	// can not access a member of class java.util.HashMap$Entry with modifiers "public"
    		System.out.println(mapGetKey.invoke(entry));	// a
    		System.out.println(hm.entrySet().iterator().next().getKey());	// a
    	}

  2. #2
    Membre éprouvé
    Profil pro
    Inscrit en
    Mai 2007
    Messages
    132
    Détails du profil
    Informations personnelles :
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Mai 2007
    Messages : 132
    Par défaut
    je crois qu'il y a un bug lié à ce sujet

    http://bugs.sun.com/bugdatabase/view...bug_id=4071957

  3. #3
    Expert éminent
    Avatar de adiGuba
    Homme Profil pro
    Développeur Java/Web
    Inscrit en
    Avril 2002
    Messages
    13 938
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Java/Web
    Secteur : Transports

    Informations forums :
    Inscription : Avril 2002
    Messages : 13 938
    Billets dans le blog
    1
    Par défaut
    Salut,

    Citation Envoyé par guiom Voir le message
    En y regardant de plus près, on voit que Map.Entry (et getKey) a un niveau package,
    Map.Entry est public ! Et puisqu'il s'agit d'une interface toutes ses méthodes sont implicitement public. Donc c'est tout à fait normal que tu puisses l'appeler via l'API de réflection...


    Quand à appeler getKey() via HashMap.Entry et la réflection j'aurais dit que c'est possible mais il semble bien que ce ne soit pas le cas.

    Et cela peut sembler logique car cela reviendrait à faire ceci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    Map.Entry entry = (Entry) hm.entrySet().iterator().next();
    HashMap.Entry hashMapEntry = (HashMap.Entry) entry;
    entry.getKey();
    HashMap.Entry n'est pas visible donc on ne peut pas la manipuler directement...

    Bref il faut faire abstraction du type exact et manipuler des Map.Entry...


    a++

  4. #4
    Membre habitué
    Inscrit en
    Février 2006
    Messages
    12
    Détails du profil
    Informations forums :
    Inscription : Février 2006
    Messages : 12
    Par défaut
    adiGuba:
    Map.Entry est public selon la javadoc, et accessible niveau package selon les sources de la VM (1.5) !! je me suis fié aux sources. Du coup, je ne sais pas lequel est juste...

    Quant à l'explication que tu donnes pour expliquer le fait que HashMap.Entry.getKey() fonctionne, elle ne me convainc pas. En effet c'est pas parce que la classe n'est pas visible (pour héritage, implémentation, etc) qu'on ne peut pas appeler une méthode public dessus.

    Globalement, je crois volontier le bug indiqué par Elmor, ça a l'air de correspondre assez bien. Je suis quand même étonné que ce genre de problème qui me semble énorme ne soit pas corrigé (comme les intervenants sur le forum Sun): il date de 97, les débuts de Java et Sun n'a toujours rien fait !!

  5. #5
    Expert éminent
    Avatar de adiGuba
    Homme Profil pro
    Développeur Java/Web
    Inscrit en
    Avril 2002
    Messages
    13 938
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations professionnelles :
    Activité : Développeur Java/Web
    Secteur : Transports

    Informations forums :
    Inscription : Avril 2002
    Messages : 13 938
    Billets dans le blog
    1
    Par défaut
    Citation Envoyé par guiom Voir le message
    adiGuba:
    Map.Entry est public selon la javadoc, et accessible niveau package selon les sources de la VM (1.5) !! je me suis fié aux sources. Du coup, je ne sais pas lequel est juste...
    Dans les sources tu as ceci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    public interface Map<K,V> {
     
    // ...
     
        interface Entry<K,V> {
     
    	K getKey();
     
    // ...
    Mais ici l'absence de visibilité ne signifie pas package-only mais public : TOUS les éléments d'une interface sont implicitement public (et Map est une interface).

    Si tu ne me crois pas je pourrais va jeter un coup d'oeil dans les specs du langage : http://java.sun.com/docs/books/jls/t...tml/j3TOC.html

    Citation Envoyé par guiom Voir le message
    En effet c'est pas parce que la classe n'est pas visible (pour héritage, implémentation, etc) qu'on ne peut pas appeler une méthode public dessus.
    J'ai juste dit qu'on ne peut pas appeler la méthode HashMap.Entry.getKey() car elle ne nous est pas visible. Par contre on peut très bien appeler la méthode Map.Entry.getKey() sur un objet HashMap.Entry.
    Le résultat sera le même mais le compilateur ne génèrerait pas le même code (dans un cas on est lié à une méthode de la classe HashMap.Entry, et dans l'autre à une méthode de l'interface Map.Entry).

    Citation Envoyé par guiom Voir le message
    Globalement, je crois volontier le bug indiqué par Elmor, ça a l'air de correspondre assez bien.
    Je n'ai pas dit le contraire... (je n'avais d'ailleurs même pas vu son message lorsque j'ai écrit le mien )

    Citation Envoyé par guiom Voir le message
    Je suis quand même étonné que ce genre de problème qui me semble énorme ne soit pas corrigé (comme les intervenants sur le forum Sun): il date de 97, les débuts de Java et Sun n'a toujours rien fait !!
    En même temps cela me semble normal qu'on ne puisse pas appeler les méthodes d'un objet qui nous est invisible...

    a++

  6. #6
    Membre habitué
    Inscrit en
    Février 2006
    Messages
    12
    Détails du profil
    Informations forums :
    Inscription : Février 2006
    Messages : 12
    Par défaut
    Mais ici l'absence de visibilité ne signifie pas package-only mais public : TOUS les éléments d'une interface sont implicitement public (et Map est une interface).

    Si tu ne me crois pas je pourrais va jeter un coup d'oeil dans les specs du langage : http://java.sun.com/docs/books/jls/t...tml/j3TOC.html
    Effectivement, chapitre 6.6.1, je vois (c'est un peu planqué...)
    All members of interfaces are implicitly public.
    On en apprend tous les jours !

    J'ai juste dit qu'on ne peut pas appeler la méthode HashMap.Entry.getKey() car elle ne nous est pas visible. Par contre on peut très bien appeler la méthode Map.Entry.getKey() sur un objet HashMap.Entry.
    Le résultat sera le même mais le compilateur ne génèrerait pas le même code (dans un cas on est lié à une méthode de la classe HashMap.Entry, et dans l'autre à une méthode de l'interface Map.Entry).
    Je me permets une finesse:
    Effectivement, HashMap.Entry n'étant pas visible, on ne peut pas avoir HashMap.Entry.getKey() directement car il faudrait forcer avec un type inaccessible (HashMap.Entry). Mais, la méthode HashMap.Entry.getKey() étant public on devrait pouvoir y accéder par l'API de reflection... qui ne veut pas le faire (raison de mon message) et identifié comme bug.

Discussions similaires

  1. API Centre de sécurité
    Par fabrice.s dans le forum VBScript
    Réponses: 0
    Dernier message: 30/09/2010, 08h31
  2. La méthode setAccessible de l'API JAVA vs sécurité
    Par wafiwafi dans le forum Langages de programmation
    Réponses: 6
    Dernier message: 23/12/2009, 23h13
  3. [API Reflection] Supprimer une classe du cache
    Par aurelienDC dans le forum API standards et tierces
    Réponses: 4
    Dernier message: 13/04/2009, 19h25
  4. Sécurité d'une connection via l'API mysql
    Par Pgs dans le forum SQL Procédural
    Réponses: 2
    Dernier message: 19/10/2007, 10h46
  5. Probleme avec la recherche directe de methodes sur une Class (API java.lang.reflect)
    Par CyberChouan dans le forum API standards et tierces
    Réponses: 14
    Dernier message: 25/01/2007, 17h12

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo