2017-04-13 80 views
1

我正在製作此狀態/菜單欄應用程序,該應用程序在Mac OS X的狀態欄中顯示當前正在播放的歌曲。要從Spotify獲取播放器狀態,我必須創建並執行AppleScript並從這得到輸出。然後使用Graphics2D中的drawString()繪製結果,Graphics2D將其設置爲BufferedImage,然後將其設置爲托盤圖標。Runnable和ScheduledExecutorService發生內存泄漏

整個代碼是4類和易於理解,可在這裏:https://github.com/ZinoKader/Menify

現在到這個問題

我可運行似乎吃起來記憶像什麼我以前見過。應用程序每秒鐘會使用2-3MB的RAM,並且如果我離開它,達到千兆字節。到目前爲止我嘗試過的方法是刷新和處理所有圖像和Graphics2D資源,刷新並關閉每個輸入流,outputstream並銷燬在AppleScripthHelper中創建的Process對象。

即使是這樣的事情,只是調用一個靜態方法開始堆積RAM很快。

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

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

和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(); 
    } 

} 

所以現在的問題是,什麼是吃了所有的內存?爲什麼似乎沒有垃圾收集?

+2

你可以發佈'AppleScriptHelper#evalAppleScript'嗎? –

+0

@JacobG。好,完成了! – Zino

回答

2

你面對的不是內存泄漏!

根據Java™教程進程和線程(https://docs.oracle.com/javase/tutorial/essential/concurrency/procthread.html),

的進程一般擁有完整,私定的基本​​運行時的資源;特別是每個進程都有自己的內存空間。

您正在每50ms創建一個新進程,這很可能是對可用內存產生影響的原因。

創建太多進程將導致thrashing,您會注意到CPU性能下降。根據流程的作用,最有可能的一種更有效的方式來實現您的目標,而無需每秒創建20個進程。

+0

我明白了。因此,每秒鐘運行該進程似乎是一個更合理的做法,但是當我嘗試這樣做時,內存使用率仍然會非常快地累加,儘管不像以前那麼快。你會建議我做什麼來更新至少每秒一次,而不是? – Zino

+0

@Zino不幸的是,如果不知道你想達到什麼目的,我不能給出太多建議。您正在運行可以在Java中完成的工作嗎? –

+0

是的,一切事實上都是用Java完成的。代碼可在https://github.com/ZinoKader/Menify – Zino