2017-04-13 264 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