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

Entrée/Sortie Java Discussion :

JNI ou pas, mais transparent


Sujet :

Entrée/Sortie Java

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Modérateur
    Avatar de ToTo13
    Homme Profil pro
    Chercheur en informatique
    Inscrit en
    Janvier 2006
    Messages
    5 793
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : Etats-Unis

    Informations professionnelles :
    Activité : Chercheur en informatique
    Secteur : Santé

    Informations forums :
    Inscription : Janvier 2006
    Messages : 5 793
    Par défaut JNI ou pas, mais transparent
    Bonjour,

    j'utilise depuis peu JNI afin d'accélérer certains traitements.
    TOUT ce qui je fais avec JNI, je peux aussi le faire avec Java car j'ai le code en double.
    Ce qui je souhaiterai, c'est pouvoir au lancement de mon appli
    - scanner toutes les classes de ma librairie
    - détecter les méthodes natives
    - si la librairie native existe et que la méthode existe dans la librairie native
    -----> Pointer sur la méthode native
    -----> Pointer sur la méthode java

    Quelque chose du genre :
    Code java : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
     
    public static void mamethode()
    {
    // Appeler la méthode native si elle a été détectée au lancement du programme, sinon la méthode java.
    }
     
    private static void mamethodenative() ;
     
    private static void mamethodejava()
    {
    // mon code java
    }

    J'aimerai éviter de faire un test à chaque appel de la méthode.

    Est ce que quelqu'un aurait une idée ?
    Merci par avance.
    Consignes aux jeunes padawans : une image vaut 1000 mots !
    - Dans ton message respecter tu dois : les règles de rédaction et du forum, prévisualiser, relire et corriger TOUTES les FAUTES (frappes, sms, d'aurteaugrafe, mettre les ACCENTS et les BALISES) => ECRIRE clairement et en Français tu DOIS.
    - Le côté obscur je sens dans le MP => Tous tes MPs je détruirai et la réponse tu n'auras si en privé tu veux que je t'enseigne.(Lis donc ceci)
    - ton poste tu dois marquer quand la bonne réponse tu as obtenu.

  2. #2
    Modérateur
    Avatar de joel.drigo
    Homme Profil pro
    Ingénieur R&D - Développeur Java
    Inscrit en
    Septembre 2009
    Messages
    12 430
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 55
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Ingénieur R&D - Développeur Java
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2009
    Messages : 12 430
    Billets dans le blog
    2
    Par défaut
    Salut,

    Premièrement, tu peux déterminer si une méthode existe dans une classe et si elle est native, par réflexion :

    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
    17
    public boolean isNativeMethodExists(Class<?> klass, String methodName, Class<?>...parameterTypes) {
       try {
          final Method method = klass.getMethod(methodName, parameterTypes);
          return Modifier.isNative(method.getModifiers());
       } catch (NoSuchMethodException | SecurityException e) {
          return false;
       }
    }
     
    public boolean isNotNativeMethodExists(Class<?> klass, String methodName, Class<?>...parameterTypes) {
       try {
          Method method = klass.getMethod(methodName, parameterTypes);
          return !Modifier.isNative(method.getModifiers());
       } catch (NoSuchMethodException | SecurityException e) {
          return false;
       }
    }
    Reste à "scanner" les classes. Ceci normalement n'est pas possible en Java. 2 solutions :
    • Utiliser une variable (liste, tableau) pour stocker toutes les classes à analyser (donc qu'il faut initialiser à la main)
    • scanner les fichiers .class dans les dossiers du classpath, ou scanner les entrées des jar s'y trouvant
      Ce que tu peux faire avec ces méthode :
      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
      17
      18
      19
      20
      21
      22
      23
      24
      25
      26
      27
      28
      29
      30
      31
      32
      33
      34
      35
      36
      37
      38
      39
      40
      41
      42
      43
      44
      45
      46
      47
      48
      49
      50
      51
      52
      53
      54
      55
      56
      57
      58
      59
      60
      61
      public static List<Class<?>> getClassesFromPackage(String packageName) throws IOException, URISyntaxException{
         return getClassNamesFromPackage(packageName).stream()
                                                     .map(className-> toClass(className))
                                                     .filter(c->c.isPresent())
                                                     .map(c->c.get())
                                                     .collect(Collectors.toList());
      }
       
      private static Optional<Class<?>> toClass(String className) {
         try {
            return Optional.of(Class.forName(className));
         } catch (ClassNotFoundException e) {
            e.printStackTrace();
            return Optional.empty();
         }
      }
       
      public static List<String> getClassNamesFromPackage(String packageName) throws IOException, URISyntaxException{
         final ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
         final List<String> names = new ArrayList<String>();;
       
         final String jarPackageName = packageName.replace(".", "/");
         final URL packageURL = classLoader.getResource(jarPackageName);
       
         if (packageURL==null) {
            throw new IllegalStateException("Not found: "+packageName);
         }
         if("jar".equals(packageURL.getProtocol())){
       
            final int start = packageName.length()>0?packageName.length()+1:0;
       
            // build jar file name, then loop through zipped entries
            String jarFileName = URLDecoder.decode(packageURL.getFile(), "UTF-8");
            jarFileName = jarFileName.substring("file:/".length(),jarFileName.indexOf("!"));
            try( JarFile jf = new JarFile(jarFileName) ) {
               for(Enumeration<JarEntry> jarEntries = jf.entries();jarEntries.hasMoreElements(); ){
      	     String entryName = jarEntries.nextElement().getName();
      	     if ( entryName.startsWith(jarPackageName) && entryName.endsWith(".class")){
                      entryName = entryName.substring(start,entryName.lastIndexOf('.'));
      		if ( !entryName.contains("/") ) {
      		    names.add(packageName+"."+entryName);
      		}
      	     }
               }
           }
         } else if ( "file".equals(packageURL.getProtocol()) ){
            final File folder = new File(packageURL.toURI().getPath());
            final File[] content = folder.listFiles();
            if ( content!=null ) {
               for (File actual : content) {
      	    String entryName = actual.getName();
                  entryName = entryName.substring(0, entryName.lastIndexOf('.'));
                  names.add(packageName+"."+entryName);
               }
           }
         }
         else {
            throw new IllegalStateException("Cannot extract class from " + packageURL);
         }
         return names;
      }
    L'expression "ça marche pas" ne veut rien dire. Indiquez l'erreur, et/ou les comportements attendus et obtenus, et donnez un Exemple Complet Minimal qui permet de reproduire le problème.
    La plupart des réponses à vos questions sont déjà dans les FAQs ou les Tutoriels, ou peut-être dans une autre discussion : utilisez la recherche interne.
    Des questions sur Java : consultez le Forum Java. Des questions sur l'EDI Eclipse ou la plateforme Eclipse RCP : consultez le Forum Eclipse.
    Une question correctement posée et rédigée et vous aurez plus de chances de réponses adaptées et rapides.
    N'oubliez pas de mettre vos extraits de code entre balises CODE (Voir Mode d'emploi de l'éditeur de messages).
    Nouveau sur le forum ? Consultez Les Règles du Club.

  3. #3
    Modérateur
    Avatar de ToTo13
    Homme Profil pro
    Chercheur en informatique
    Inscrit en
    Janvier 2006
    Messages
    5 793
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : Etats-Unis

    Informations professionnelles :
    Activité : Chercheur en informatique
    Secteur : Santé

    Informations forums :
    Inscription : Janvier 2006
    Messages : 5 793
    Par défaut
    Merci beaucoup pour ces informations.

    Je suppose que pour tester si une méthode java déclarée "native", pointe bien sur vers une méthode native, il faut tenter de l'appeler. Correct ?

    Une idée comment pointer efficacement sur l'une ou l'autre des méthodes ?
    Pointer sur une classe ou une autre est facile avec des interfaces, mais des méthodes... pas d'idée :-(
    Consignes aux jeunes padawans : une image vaut 1000 mots !
    - Dans ton message respecter tu dois : les règles de rédaction et du forum, prévisualiser, relire et corriger TOUTES les FAUTES (frappes, sms, d'aurteaugrafe, mettre les ACCENTS et les BALISES) => ECRIRE clairement et en Français tu DOIS.
    - Le côté obscur je sens dans le MP => Tous tes MPs je détruirai et la réponse tu n'auras si en privé tu veux que je t'enseigne.(Lis donc ceci)
    - ton poste tu dois marquer quand la bonne réponse tu as obtenu.

  4. #4
    Modérateur
    Avatar de joel.drigo
    Homme Profil pro
    Ingénieur R&D - Développeur Java
    Inscrit en
    Septembre 2009
    Messages
    12 430
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 55
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Ingénieur R&D - Développeur Java
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2009
    Messages : 12 430
    Billets dans le blog
    2
    Par défaut
    En gros, tu voudrais savoir si l'appel d'une méthode native va soulever une UnsatisfiedLinkError ?

    Je pense qu'on devrait le faire en amont, au moment du chargement de bibliothèque native (System.loadLibrary()), en chargeant le bon jar (voir URLClassLoader) en fonction de l'echec ou non du chargement de bibliothèque native (en faisant 2 jar identiques, l'un avec les classes avec les méthode natives. l'autre avec les classes avec les méthodes non natives, mêmes noms, mêmes packages, mêmes méthodes, même signatures, etc.). Plus besoin de scan ou de test : il te suffit de programmer avec l'un des deux jars (de préférence le non natif pour faire les tests dans l'IDE) dans le classpath, mais de ne pas l'exporter dans le classpath, mais en intégrant les 2 fichiers jar dans le jar de l'application.

    Sinon, je ne sais pas si on peut tester si l'appel d'une méthode native va soulever une UnsatisfiedLinkError. La méthode bourrine serait d'appeler la méthode et en cas d'exception rediriger vers la méthode non native.

    On pourrait faire ça par réflexion, mais on perdrait l'avantage de pouvoir tester les types des paramètres à la compilation (sans parler de la completion), donc il faudrait faire attention aux paramètres qu'on passe (et on ne sait qu'on s'est planté qu'à l'exécution), ou alors il faudrait faire un handler pour chaque couple de méthodes, avec les bons paramètres (du coup, plus vraiment d'intérêt de scanner). On pourrait aussi générer ces classes en avance, ou éventuellement dynamiquement au lancement de l'application.

    Ou alors faire un handler avec des lambdas, mais on est obligé systématiquement de duppliquer l'appel, et puis ça peut devenir lourd d'écrire tous les appels comme ça, sans parler des enchainements d'appels...

    Genre quelque chose comme ça :

    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
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    public class CallHandler<T> {
     
    	private boolean callNative=true;
     
    	public T call(Supplier<T> nativeCall, Supplier<T> nonNativeCall) {
     
    		if( callNative ) {
    			try {
    				return nativeCall.get();
    			}
    			catch( UnsatisfiedLinkError e ) {
    				callNative=false;
    				return nonNativeCall.get();
    			}
    		}
    		else {
    			return nonNativeCall.get();
    		}
     
    	}
     
    	public static class Test {
    		public native int nativeTestMethod(int param);
    		public int testMethode(int param) {
    			return param;
    		}
    	}
     
    	public static void main(String[] args) {
     
    		Test test=new Test();
     
    		System.out.println(new CallHandler<Integer>().call(()->test.nativeTestMethod(100), ()->test.testMethode(100)));
     
    	}
     
    }
    L'expression "ça marche pas" ne veut rien dire. Indiquez l'erreur, et/ou les comportements attendus et obtenus, et donnez un Exemple Complet Minimal qui permet de reproduire le problème.
    La plupart des réponses à vos questions sont déjà dans les FAQs ou les Tutoriels, ou peut-être dans une autre discussion : utilisez la recherche interne.
    Des questions sur Java : consultez le Forum Java. Des questions sur l'EDI Eclipse ou la plateforme Eclipse RCP : consultez le Forum Eclipse.
    Une question correctement posée et rédigée et vous aurez plus de chances de réponses adaptées et rapides.
    N'oubliez pas de mettre vos extraits de code entre balises CODE (Voir Mode d'emploi de l'éditeur de messages).
    Nouveau sur le forum ? Consultez Les Règles du Club.

  5. #5
    Modérateur
    Avatar de ToTo13
    Homme Profil pro
    Chercheur en informatique
    Inscrit en
    Janvier 2006
    Messages
    5 793
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : Etats-Unis

    Informations professionnelles :
    Activité : Chercheur en informatique
    Secteur : Santé

    Informations forums :
    Inscription : Janvier 2006
    Messages : 5 793
    Par défaut
    Oui, j'ai l'impression qu'il n'y a pas de solution facile :-(
    Dans mon cas je n'ai que peu de méthodes natives et elles sont toutes dans la même librairie.
    Je pense à une solution du type
    - une interface qui désigne les classes ayant des méthodes natives
    - scan de toutes les classes
    - les classes qui implémentent l'interface ont une méthode static qui teste chaque méthode native et fait le lien qu'il faut. Dans ce cas le lien serait un simple test sur un booléen.

    C'est moche, c'est long, mais simple.

    En tout cas merci pour tes réponses.
    Consignes aux jeunes padawans : une image vaut 1000 mots !
    - Dans ton message respecter tu dois : les règles de rédaction et du forum, prévisualiser, relire et corriger TOUTES les FAUTES (frappes, sms, d'aurteaugrafe, mettre les ACCENTS et les BALISES) => ECRIRE clairement et en Français tu DOIS.
    - Le côté obscur je sens dans le MP => Tous tes MPs je détruirai et la réponse tu n'auras si en privé tu veux que je t'enseigne.(Lis donc ceci)
    - ton poste tu dois marquer quand la bonne réponse tu as obtenu.

  6. #6
    Modérateur
    Avatar de joel.drigo
    Homme Profil pro
    Ingénieur R&D - Développeur Java
    Inscrit en
    Septembre 2009
    Messages
    12 430
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 55
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Ingénieur R&D - Développeur Java
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Septembre 2009
    Messages : 12 430
    Billets dans le blog
    2
    Par défaut
    Citation Envoyé par ToTo13 Voir le message
    - une interface qui désigne les classes ayant des méthodes natives
    A la place, tu peux parcourir simplement toutes les méthodes de classes pour tester si l'une est native.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    public static boolean hasNativeMethod(Class<?> klass) {
       for(Method method : klass.getMethods()) {
          if ( Modifier.isNative(method.getModifiers()) ) {
    	  return true;
          }
       }
       return false;
    }
    Citation Envoyé par ToTo13 Voir le message
    - les classes qui implémentent l'interface ont une méthode static qui teste chaque méthode native et fait le lien qu'il faut. Dans ce cas le lien serait un simple test sur un booléen.
    Pourquoi mettre une méthode statique dans chaque classe : une seule suffit pour l'ensemble des classes. Ou alors tu as besoin de traiter des informations spécifiques pour chaque classe et chaque méthode native. Peut-être qu'un fichier descripteur à part pourrait faire l'affaire. Ou alors une annotation (mais je ne sais pas si on peut faire une annotation sur une méthode native). Peut-être un aspect serait la solution (pour rediriger l'appel vers la méthode non native si c'est ce que tu cherches à faire).
    Par contre, je ne comprends pas ce que tu veux dire par "le lien serait un simple test sur un booléen".
    L'expression "ça marche pas" ne veut rien dire. Indiquez l'erreur, et/ou les comportements attendus et obtenus, et donnez un Exemple Complet Minimal qui permet de reproduire le problème.
    La plupart des réponses à vos questions sont déjà dans les FAQs ou les Tutoriels, ou peut-être dans une autre discussion : utilisez la recherche interne.
    Des questions sur Java : consultez le Forum Java. Des questions sur l'EDI Eclipse ou la plateforme Eclipse RCP : consultez le Forum Eclipse.
    Une question correctement posée et rédigée et vous aurez plus de chances de réponses adaptées et rapides.
    N'oubliez pas de mettre vos extraits de code entre balises CODE (Voir Mode d'emploi de l'éditeur de messages).
    Nouveau sur le forum ? Consultez Les Règles du Club.

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. fonction qui ne s'execute pas mais qui ne retourne pas d'erreur
    Par duplo dans le forum Général JavaScript
    Réponses: 2
    Dernier message: 03/06/2006, 21h43
  2. [Mac] Lien ne fonctionnant pas mais ok sous Windows
    Par bractar dans le forum Balisage (X)HTML et validation W3C
    Réponses: 11
    Dernier message: 26/01/2006, 18h38
  3. La FAQ qui ne marche pas mais pourquoi?
    Par Antoine_1977 dans le forum Access
    Réponses: 3
    Dernier message: 27/09/2005, 16h22
  4. [Process] pb exec sous unix, ne plante pas mais ne fait rien
    Par NiBicUs dans le forum API standards et tierces
    Réponses: 3
    Dernier message: 10/12/2004, 05h27
  5. [Système] loadLibrary ne marche pas mais Load oui
    Par fredericL dans le forum API standards et tierces
    Réponses: 5
    Dernier message: 26/05/2004, 15h32

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