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

Java Discussion :

Compiler des .class en code natif


Sujet :

Java

  1. #1
    Membre chevronné Avatar de Mobius
    Profil pro
    none
    Inscrit en
    Avril 2005
    Messages
    463
    Détails du profil
    Informations personnelles :
    Localisation : France, Isère (Rhône Alpes)

    Informations professionnelles :
    Activité : none

    Informations forums :
    Inscription : Avril 2005
    Messages : 463
    Par défaut Compiler des .class en code natif
    Je cherche le moyen de compiler des fichiers .class (contenant du byte code java).
    Le code ainsi obtenu doit encore pouvoir être chargé par la JVM.

    J'ai donc pensé a compilé mes classes en utilisant GCJ qui peut générer une librairie partagé (un fichier .so).

    Pour utilisé cette librairie, j'ai pensé charger cette librairie avec la méthode "System.loadLibrary" et pouvoir réécrire une implémentation de la classe en déclarant toutes les méthodes "native".

    Voici mon code:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    public class Main {
    	static {
    		System.loadLibrary("helloworld");
    	}
    	public static void main(String[] args) throws Exception {
    		HelloWorld.sayHello();
    	}
    }
    La méthode HelloWorld.sayHello étant bien déclaré native.

    Le problème c'est que j'ai une erreur lors de l'execution
    [java] Exception in thread "main" java.lang.UnsatisfiedLinkError: sayHello
    [java] at HelloWorld.sayHello(Native Method)
    [java] at Main.main(Unknown Source)
    [java] Java Result: 1
    Si je comprend bien l'erreur, la JVM ne trouve pas la méthode native correspondante.

    Pour construire ma librairie partagé, j'ai créé une implémentation (non native) de la classe HelloWorld que j'ai ensuite compilé avec GCJ.
    Je suppose que la compilation GCJ n'est pas tout a fait correcte et que le résultat ne respecte pas les convention JNI.

    Première question : Est ce faisable ?
    Deuxième : Comment ? (je suppose qu'il manque quelque chose lors de la compimation avec GCJ mais je ne sais pas quoi).


    PS: Je suis prêt à compiler mon code avec autre chose que GCJ si besoin.

  2. #2
    Expert éminent
    Avatar de tchize_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2007
    Messages
    25 482
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 482
    Par défaut
    les classes compilées avec gcj s'utilisent comme toutes les autres classes. En fait, qu'elles soient compilées avec GCJ ou avec javac, elles devraient avoir le meme comportement. System.loadLibrary, c'est pour charger des librairies natives (genre du code C par exemple), pas pour charger des classes java compilées avec gcj. Pour les classes java, ca reste le principe du classpath et des import qui est à utiliser.

  3. #3
    Membre chevronné Avatar de Mobius
    Profil pro
    none
    Inscrit en
    Avril 2005
    Messages
    463
    Détails du profil
    Informations personnelles :
    Localisation : France, Isère (Rhône Alpes)

    Informations professionnelles :
    Activité : none

    Informations forums :
    Inscription : Avril 2005
    Messages : 463
    Par défaut
    Sauf que par défaut si on utilise GCJ pour générer des fichier .class (option -C), cela compile les classe sous forme de bytecode. J'aimerai pouvoir générer ces classes sous forme de code natif.
    Pour le reste je suis d'accord (sauf que du coup ca correspond pas a mon besoin)

  4. #4
    Modérateur

    Profil pro
    Inscrit en
    Septembre 2004
    Messages
    12 582
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Septembre 2004
    Messages : 12 582
    Par défaut
    Mais... Du code natif ne peut être lié à du bytecode que par l'utilisation de JNI.

    Et Java, ironiquement, est totalement incapable de décrire des fonctions répondant aux conventions de liaison de JNI.
    N'oubliez pas de consulter les FAQ Java et les cours et tutoriels Java

  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
    Salut,

    Citation Envoyé par Mobius Voir le message
    J'aimerai pouvoir générer ces classes sous forme de code natif.
    Ce n'est pas possible ! Un fichier *.class ne peut pas être un fichier natif.

    Si tu produit du code natif avec GCJ, il faudra générer un exécutable natif pour pouvoir l'exécuter

    a++

  6. #6
    Membre chevronné Avatar de Mobius
    Profil pro
    none
    Inscrit en
    Avril 2005
    Messages
    463
    Détails du profil
    Informations personnelles :
    Localisation : France, Isère (Rhône Alpes)

    Informations professionnelles :
    Activité : none

    Informations forums :
    Inscription : Avril 2005
    Messages : 463
    Par défaut
    Citation Envoyé par adiGuba Voir le message
    Ce n'est pas possible ! Un fichier *.class ne peut pas être un fichier natif.
    D'ou l'idée de compilé mes classes en code natif dans une librairie externe et de faire le lien avec JNI.
    Mais cela semble difficilement faisable.
    La réponse de thelvin semble confirmer ma crainte.

  7. #7
    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
    Pourquoi une telle obsession pour générer du code natif ???

    a++

  8. #8
    Invité
    Invité(e)
    Par défaut
    Par code natif, tu entends code machine ?
    Si oui, à mon avis, il n'y a pas d'autre moyen que de partir du code source d'une JVM opensource car c'est là que se situe le code natif de tout ce qui est lié au systèmes.

  9. #9
    Membre chevronné Avatar de Mobius
    Profil pro
    none
    Inscrit en
    Avril 2005
    Messages
    463
    Détails du profil
    Informations personnelles :
    Localisation : France, Isère (Rhône Alpes)

    Informations professionnelles :
    Activité : none

    Informations forums :
    Inscription : Avril 2005
    Messages : 463
    Par défaut
    Citation Envoyé par adiGuba Voir le message
    Pourquoi une telle obsession pour générer du code natif ???
    Pour des raisons de prédictibilité d’exécution du code dans un contexte très particulier.

    Citation Envoyé par Nudger
    il n'y a pas d'autre moyen que de partir du code source d'une JVM opensource
    J'esperai bien que si Merci pour cette piste. Je vais essayé de l'explorer mais j'ai peur que la solution que j'en tirerai soit trop liée à la JVM en question.
    Dans le cadre des travaux que j'effectue, je ne peux utiliser que 2 JVM qui sont à mille lieux d'être opensource.
    Il y a bien une facon d'accèder au compilateur de la JVM au travers d'une API standard mais je n'arrive pas à l'utiliser correctement (cf. ce post).

  10. #10
    Expert éminent
    Avatar de tchize_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2007
    Messages
    25 482
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 482
    Par défaut
    Citation Envoyé par Mobius Voir le message
    Pour des raisons de prédictibilité d’exécution du code dans un contexte très particulier.
    Le code natif (que ce soit gcj ou autre) ,n'y changera rien. Du code java a besoin d'une JVM pour tourner. Ce que fait GCJ, c'est simplement supprimer la partie interprétation/compilation à la volée des jvm. C'est tout. Ca reste pour le reste un jvm, avec son garbage collector, ses threads, sur un OS non prédictible, avec des disques à temps d'accès non prédictible, une ram à temps d'accès non prédictible et un CPU multi coeur qui fait du branch and bound non prédictible. Tout ça rend les temps de calcul d'une application non prédicitible, ce qui rend extrèmement compliquée, à l'heure actuelle, l'optimisation fine, car on ne sait jamais si on a optimisé ou si on a juste du bol avec les heuristique et que demain on aura plus ce bol.


    Si vous avez besoin de faire du real time, vous devez vous orientez vers les jvm spécifiques et payant de oracle, qui nécessitent, au passage, des OS realtime. D'ailleurs quand je vois des OS "realtime" tourner sur des CPU x86, ça me fait doucettement rire

  11. #11
    Membre chevronné Avatar de Mobius
    Profil pro
    none
    Inscrit en
    Avril 2005
    Messages
    463
    Détails du profil
    Informations personnelles :
    Localisation : France, Isère (Rhône Alpes)

    Informations professionnelles :
    Activité : none

    Informations forums :
    Inscription : Avril 2005
    Messages : 463
    Par défaut
    Citation Envoyé par tchize_ Voir le message
    Si vous avez besoin de faire du real time, vous devez vous orientez vers les jvm spécifiques et payant de oracle, qui nécessitent, au passage, des OS realtime. D'ailleurs quand je vois des OS "realtime" tourner sur des CPU x86, ça me fait doucettement rire
    Je suis entierement d'accord, mais le but n'est pas de faire tourner sur mon portable mais sur un cluster dédié avec un OS temps réel.
    Je suis également au courant du besoin d'avoir une JVM temps réel, c'est pour ca que j'ai dis que je ne pouvais utiliser que 2 JVM (Java RTS d'Oracle et Websphere RT d'IBM). Les autres JVM RT étant un peu trop exotique.
    La problématique n'est donc pas là.

    Actuellement, ce qui me pose problème est l'interprétation du bytecode par la JVM. Pour pallier a ce problème, Oracle propose l'ITC (Initialization Time Compilation). Après avoir expérimenté cette solution, j'ai mis en évidence un certains nombre de problèmes lié à notre environnement.
    De son coté, IBM propose la compilation AOT (Ahead-Of-Time). Pas encore expérimenté à l'heure actuelle. Mais j'ai bon espoir que ca répondra à mes problème (mais avant de l'expérimenter j'aimerai approfondir les pistes que j'ai commencé a suivre).
    Dans les deux cas, il s'agit de solution spécifique à la JVM.

    Lors de mes recherches, j'ai été amené a imaginer d'autre solution que j'essaye d'implémenter. D'un point du vue théorique, je ne vois pas d'impossibilité mais je n'arrive tout simplement pas à mettre en oeuvre ces solutions.

    J'aimerai donc pouvoir me concentrer sur ma problématique

  12. #12
    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 Mobius Voir le message
    J'aimerai donc pouvoir me concentrer sur ma problématique
    Précises ta problématique alors !
    Tu veux exécuter du code natif ou tu veux exécuter du code en temps-réel ? Ce n'est pas forcément la même chose !

    Ce n'est pas parce qu'un code est compilé en natif qu'il s'exécutera en temps-réel !


    a++

  13. #13
    Expert éminent
    Avatar de tchize_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2007
    Messages
    25 482
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 482
    Par défaut
    gcj est un "simple" remplacement à javac. (j'exagère mais bon).

    comme déjà dit, il n'a pas pour but de générer des librairies utilisable pour JNI/JNA, il a pour but de précompiler les .class dans la plateforme courante.

    Donc (car ce n'est pas clair dans votre énoncé).

    Soit vous avez tenté de compiler 1 ou plusieurs classes java en .so et tentez maintenant de l'utiliser dans votre JVM "classique"-> ca ne peut pas marcher

    Soit vous vous avez une vraie classe native à charger via System.loadLibrary() et vous avez des erreurs. Dans ce cas, il serait judicieux de poster le code de la classe native, ansi que le code natif que vous avez balancé dans le compilateur JNI/JNA, que ceux qui s'y connaissent puissent regarder ce qui se passe.

    Pour rappel, le but de gcj est de faire des .so et des ELF/ELF64. Un fois que vous partez avec gcj, votre application finale devra estre un ELF compilé avec gcj, pas un jar à lancer avec java -jar

  14. #14
    Membre chevronné Avatar de Mobius
    Profil pro
    none
    Inscrit en
    Avril 2005
    Messages
    463
    Détails du profil
    Informations personnelles :
    Localisation : France, Isère (Rhône Alpes)

    Informations professionnelles :
    Activité : none

    Informations forums :
    Inscription : Avril 2005
    Messages : 463
    Par défaut
    J'imagine bien que le seul fait de compiler en code natif ne va pas executer mon programme en temps réel.

    Pour le moment j'explore différente possibilité dont l'une est de compiler mon code sous forme native. Ceci afin d'éviter d'avoir du bytecode interprété qui est réputé comme une source de jitter à l'execution dans un environnement temps réel (L'interprétation des méthodes étant systématiquement remonté par la JVM d'Oracle quand on positionne l'option -XX:+LogJitterProneEvents).
    L'ITC proposé par Oracle pour résoudre ce problème (l'interprétation du bytecode) ne répond pas complètement à mon problème car dans certain cas tordu, il m'arrive encore d'avoir du code interprété.
    Afin d'éviter d'avoir du code interprété, je voudrais pouvoir compiler à l'avance (principe de l'AOT) tout le code critique dans le projet. Cela permet de ne plus avoir de bytecode et donc de réduire le jitter sur ce point.
    La JVM d'oracle ne proposant pas d'AOT, j'envisage de passer sur la JVM d'IBM pour voir ce qu'il en ait.

    Quoi qu'il en soit, aucune piste n'est écarté et je voudrais pouvoir comparer chacune d'entre elle (si c'est possible) afin de retenir celle qui correspondra le plus à nos besoin.

    Je me concentre actuellement sur la précompilation du code avec la JVM d'Oracle. Je voudrais donc que tout le code soit compilé en code natif avant son exécution.
    La solution présenté au début de ce post est censé répondre à cette problématique. Si ce n'est pas réalisable, je serai bien entendu obligé d'abandonner cette piste pour en privilégier une autre.
    Avant de l'abandonner, je voulais savoir si quelqu'un avait une idée de la façon dont je pouvais réaliser ce que j'essaye de faire.

    Ce n'est qu'une piste que j'explore en essayant éventuellement d'apporter de nouvelles solutions.
    Cela ne veut pas dire que c'est la meilleur solution mais j'aimerai pouvoir la comparer à d'autre si cela est possible.

  15. #15
    Expert éminent
    Avatar de tchize_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2007
    Messages
    25 482
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 482
    Par défaut
    les code "natif" généré par gcj est propre à gcj, comme le code natif créé par ibm est propre à ibm et le code natif généré par oracle propre à oracle.

    autrement dit, les .so générés par gcj ne sont utilisable que dans le cadre d'un appli full native entièrement compilée avec gcj. Et la jvm de gcj ne garanti par de RT.


    vous pouvez bien entendu compiler tout avec gcj et comparer les parformance. attention cependant que gcj n'est pas une implémentation complète de la jvm

  16. #16
    Membre chevronné Avatar de Mobius
    Profil pro
    none
    Inscrit en
    Avril 2005
    Messages
    463
    Détails du profil
    Informations personnelles :
    Localisation : France, Isère (Rhône Alpes)

    Informations professionnelles :
    Activité : none

    Informations forums :
    Inscription : Avril 2005
    Messages : 463
    Par défaut
    Citation Envoyé par tchize_ Voir le message
    gcj est un "simple" remplacement à javac. (j'exagère mais bon).

    comme déjà dit, il n'a pas pour but de générer des librairies utilisable pour JNI/JNA, il a pour but de précompiler les .class dans la plateforme courante.

    Donc (car ce n'est pas clair dans votre énoncé).

    Soit vous avez tenté de compiler 1 ou plusieurs classes java en .so et tentez maintenant de l'utiliser dans votre JVM "classique"-> ca ne peut pas marcher

    Soit vous vous avez une vraie classe native à charger via System.loadLibrary() et vous avez des erreurs. Dans ce cas, il serait judicieux de poster le code de la classe native, ansi que le code natif que vous avez balancé dans le compilateur JNI/JNA, que ceux qui s'y connaissent puissent regarder ce qui se passe.

    Pour rappel, le but de gcj est de faire des .so et des ELF/ELF64. Un fois que vous partez avec gcj, votre application finale devra estre un ELF compilé avec gcj, pas un jar à lancer avec java -jar
    Je pensais utiliser GCJ pour compiler des sources Java sous la forme de librairie native et de réutiliser ces librairies native dans un programme java "standard".
    D'après ce que j'ai compris GCJ ne permet pas de réaliser cela (dommage)
    D'ou la question : existe-il un utilitaire équivalent permettant de réaliser cela ?
    J'ai bien trouvé TurboJ qui semble faire quelque chose d'équivalent mais le projet semble abandonné et je ne trouve pas de site sur lequel le récupérer.

  17. #17
    Membre chevronné Avatar de Mobius
    Profil pro
    none
    Inscrit en
    Avril 2005
    Messages
    463
    Détails du profil
    Informations personnelles :
    Localisation : France, Isère (Rhône Alpes)

    Informations professionnelles :
    Activité : none

    Informations forums :
    Inscription : Avril 2005
    Messages : 463
    Par défaut
    Citation Envoyé par tchize_ Voir le message
    les code "natif" généré par gcj est propre à gcj, comme le code natif créé par ibm est propre à ibm et le code natif généré par oracle propre à oracle.
    Java étant un langage comme un autre, il devrait théoriquement être possible de compiler du code java sous forme native (fichier .so) et que ce code réponde aux conventions de liaison de JNI.

    Reste à passer de la théorie a la pratique...

  18. #18
    Invité
    Invité(e)
    Par défaut
    Oui c'est possible et ce code pour être natif doit savoir se passer de la JVM.
    Donc il doit lui-même savoir gérer la mémoire, les interfaces entrées/sorties, le threading, ....

    Rien que la problématique de l'allocation de la mémoire et de la désallocation doit être coton si on n'a pas la JVM et le Garbage Collecting.

    C'est pour ça que je disais qu'il vaut mieux partir d'un code d'une JVM opensource et l'adapter pour qu'il fabrique un .so qui pourra ensuite éventuellement être ré-utilisé via JNI par une vraie JVM.

  19. #19
    Membre Expert
    Avatar de professeur shadoko
    Homme Profil pro
    retraité nostalgique Java SE
    Inscrit en
    Juillet 2006
    Messages
    1 257
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 76
    Localisation : France, Hauts de Seine (Île de France)

    Informations professionnelles :
    Activité : retraité nostalgique Java SE

    Informations forums :
    Inscription : Juillet 2006
    Messages : 1 257
    Par défaut
    Citation Envoyé par tchize_ Voir le message
    et un CPU multi coeur qui fait du branch and bound non prédictible.
    ma culture générale ne va pas jusque là: mes connaissances "hardeuses" sont substandard et datent de l'age de pierre .... en quoi et comment le CPU fait du "branch and bound"? tu peux me faire des liens web sur ce sujet? merci!

  20. #20
    Expert éminent
    Avatar de tchize_
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Avril 2007
    Messages
    25 482
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 46
    Localisation : Belgique

    Informations professionnelles :
    Activité : Ingénieur développement logiciels
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2007
    Messages : 25 482
    Par défaut
    j'en ai pas sous la main, mais en gros le CPU, devant une instruction de jump conditionnel, avant qu'il n'aie le résultat charge la zone mémoire vers laquelle il y a la plus grande probabilité de résultat. Cessont des heuristique, donc hasardeux. Si il "rate", il a un cache de premier niveau qui ne lui sert à rien, il doit le vider et charger la bonne zone mémoire, d'ou une perte de temps alors que si il réussi, gain de temps, le cache est bon

    edit: et à vue de pifomètre, c'est pas du branch and bound désolé pour le mauvais terme

Discussions similaires

  1. compiler des classes qui en importe d'autre
    Par bogizo dans le forum Débuter avec Java
    Réponses: 10
    Dernier message: 28/08/2008, 03h25
  2. compilation des classe c++
    Par lobna dans le forum Windows
    Réponses: 2
    Dernier message: 17/05/2008, 11h07
  3. [Tomcat/Struts]non compilations des classes!
    Par jazer dans le forum Struts 1
    Réponses: 9
    Dernier message: 11/07/2006, 14h03
  4. [Débutant] J'ai un problème avec la compilation des classes
    Par Paulinho dans le forum Eclipse Java
    Réponses: 2
    Dernier message: 19/11/2005, 14h23
  5. [javac] code pour lancer la compilation des classes
    Par viena dans le forum Général Java
    Réponses: 6
    Dernier message: 19/07/2004, 17h41

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