Bonjour,
J'utilise JNI pour pouvoir accéder à l'API fmod (C++) à partir de mon application java.
Pour ça, j'utilise la librairie nativeFmodEx.
Dans tous mes tests que j'avais fait avant de me lancer, je n'ai eu aucun problème, je suis donc parti confiant sur mon projet !
Seulement maintenant que je l'ai intégré dans mon lecteur audio, j'ai des soucis. Déjà, il faut savoir que toutes mes commandes JNI sont exécutées dans un thread à part.
Pour éviter tout accès concurrent, j'ai mis en place un système de file d'attente qui exécute une à une les actions demandées depuis l'interface (chargement fichier, lecture, récupération de la position dans le média pour mettre à jour la position...).
Le problème que j'ai, c'est quand j'appelle la méthode de la récupération de la position. J'ai un plantage lié à JNI (la mémoire ne peut pas être read...) de façon aléatoire (des fois ça plante dans la première seconde de la chanson, des fois elle peut être lue en entier...), sachant que cette méthode est appelée toute les 500ms (je rajoute une demande à la file d'attente toute les 500 ms).
Ce qui m'étonne le plus dans tout ça, c'est que ce n'est pas la méthode qui récupère la position qui plante, mais le crash arrive quand je supprime l'action correspondante de ma file d'attente, après qu'elle ai été exécutée... voilà ma boucle de gestion de file d'attente :
Je pense que c'est lié à la destruction de l'objet. J'ai donc essayé manuellement, à la fin de la méthode "runAndDeallocate", de mettre à null le seul pointeur qui accède à JNI, mais le plantage arrive toujours au même endroit...
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 public void threatQueue() { LOGGER.info("ThreatQueue must treat " + PlayerActionQueue.this.actionsToDo.size() + " actions"); while (PlayerActionQueue.this.actionsToDo.size() > 0) { LOGGER.info("Start " + PlayerActionQueue.this.actionsToDo.get(0).getClass().getSimpleName()); try { PlayerActionQueue.this.actionsToDo.get(0).runAndDeallocate(); } finally { LOGGER.info("Fin de l'action " + PlayerActionQueue.this.actionsToDo.get(0).getClass().getSimpleName()); synchronized (PlayerActionQueue.this.actionsToDo) { LOGGER.info("Avant remove " + PlayerActionQueue.this.actionsToDo.size()); PlayerActionQueue.this.actionsToDo.remove(0); //ligne qui plante LOGGER.info("Après remove"); } } } LOGGER.info("ThreatQueue end of method"); }
voilà le code de runAndDeallocate :
Du coup la méthode de run() :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8 public void runAndDeallocate() { try { run(); } finally { this.player = null; //Player est un objet que j'ai codé et qui contient les objets du wrapper JNI } }
et le code de this.player.getCurrentSound().getMediaTime() :
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10 public void run() { try { this.player.checkCurrentSoundInitialized(); //vérifie juste que le pointeur du son n'est pas null this.millisecondPosition = this.player.getCurrentSound().getMediaTime(); } catch (PlayerException e) { this.logger.error(StackTracer.getStackTrace(e)); this.player.getMessageNotifier().sendError(e.getMessage()); } }
Pour info, l'instance de Player que je met à null est présente dans la fenêtre principale de mon application, donc il ne doit pas être détruit à ce moment là.
Code : Sélectionner tout - Visualiser dans une fenêtre à part
1
2
3
4
5
6
7
8
9
10 protected int getMediaTime() throws PlayerException { this.logger.info("JNI : Avant récupération position"); IntBuffer result = BufferUtils.newIntBuffer(1); Player.errorCheck(this.channel.getPosition(result, FMOD_TIMEUNIT_MS)); this.logger.info("JNI : Après récupération positione"); int mediaTime = result.get(); result.clear(); return mediaTime; }
Pour moi toutes les ressources sont proprement désallouées (clear sur le IntBuffer, et affectation de null pour le player de l'objet qui est supprimé de la liste, donc je ne voit pas ce qui peut géner la suppression de mon objet action. et vu que mon crash se produit quand mon objet action est enlevé de la liste des actions, je vois pas ce que ça peut être d'autre...
Si quelqu'un à une piste je suis preneur, là je sèche complet, surtout que j'ai très peu d'expérience en ce qui concerne JNI...
Merci et à plus !
Partager