1

Je crée cette application de barre de menu qui affiche la chanson en cours de lecture dans la barre d'état de Mac OS X. Pour obtenir le statut de lecteur de Spotify, je dois créer et exécuter un AppleScript et obtenir la sortie de cela. Le résultat est ensuite dessiné à l'aide de drawString() à partir de Graphics2D, qui est défini sur un BufferedImage qui est ensuite défini comme l'icône de la barre d'état.Fuite de mémoire avec Runnable et ScheduledExecutorService

Le code entier est 4 classes et facile à suivre, ici: https://github.com/ZinoKader/Menify

maintenant sur le problème

Mon runnable semble manger de la mémoire comme je ne l'ai vu avant. Chaque seconde, l'application utilise 2-3 Mo plus de RAM, et atteint pour les gigaoctets si je le laisse être. Ce que j'ai essayé jusqu'ici est de vider et de disposer de toutes mes images et ressources Graphics2D, vider et fermer chaque inputtream, outputtream et détruire l'objet de processus que je crée dans AppleScripthHelper.

Même quelque chose comme ça, l'appel d'une méthode statique commence à accumuler de la RAM très rapidement.

final Runnable refreshPlayingText =() -> { 
    AppleScriptHelper.evalAppleScript(ScriptConstants.SPOTIFY_META_DATA_SCRIPT); 
} 

//update every 50ms 
mainExecutor.scheduleAtFixedRate(refreshPlayingText, 0, 50, TimeUnit.MILLISECONDS); 

et AppleScriptHelper

class AppleScriptHelper { 

private static final int EOF = -1; 

static String evalAppleScript(String code) { 

    String[] args = { "osascript", "-e", code }; 

    try { 
     Process process = Runtime.getRuntime().exec(args); 
     process.waitFor(); 
     ByteArrayOutputStream baos = new ByteArrayOutputStream(); 
     byte[] bigByteArray = new byte[4096]; 

     InputStream is = process.getInputStream(); 
     copyLargeStream(is, baos, bigByteArray); //write to outputstream 

     String result = baos.toString().trim(); 

     is.close(); 
     baos.flush(); 
     baos.close(); 
     process.destroyForcibly(); 

     return result; 

    } catch (IOException | InterruptedException e) { 
     Log.debug(e); 
     return null; 
    } 
} 

private static void copyLargeStream(InputStream input, OutputStream output, byte[] buffer) throws IOException { 
    int n; 
    while (EOF != (n = input.read(buffer))) { 
     output.write(buffer, 0, n); 
    } 
    input.close(); 
    output.close(); 
    } 

} 

La question est, ce qui gruge tout cela RAM? Pourquoi apparemment rien n'est ramassé?

+2

Pouvez-vous poster 'AppleScriptHelper # evalAppleScript'? –

+0

@JacobG. D'accord, c'est fait! – Zino

Répondre

2

Ce que vous faites face n'est pas une fuite de mémoire!

Selon Java ™ Tutoriels pour les processus et les threads (https://docs.oracle.com/javase/tutorial/essential/concurrency/procthread.html),

Un processus a généralement un ensemble complet, privé des ressources d'exécution de base; en particulier, chaque processus a son propre espace mémoire.

Vous créez un nouveau processus toutes les 50ms, ce qui est probablement ce qui pèse sur votre mémoire disponible.

Si vous créez trop de processus, vous obtiendrez thrashing et vous remarquerez des performances processeur réduites. En fonction de ce que fait le processus, il existe probablement un moyen plus efficace d'atteindre votre objectif sans créer 20 processus par seconde.

+0

Je vois. Donc, exécuter le processus à chaque seconde semble être une chose plus raisonnable à faire, mais quand j'essaie cela, l'utilisation de la mémoire RAM s'accumule toujours très rapidement, mais pas aussi rapidement qu'avant. Que suggérez-vous que je fasse pour mettre à jour quelque chose au moins chaque seconde, à la place? – Zino

+0

@Zino Malheureusement, je ne peux pas donner beaucoup de conseils sans savoir ce que vous essayez d'atteindre. Est-ce que le processus que vous exécutez quelque chose qui peut être fait en Java? –

+0

Oui, tout est fait en Java. Le code est disponible sur https://github.com/ZinoKader/Menify – Zino