Java Runnable和ScheduledExecutorService内存泄漏

Java Runnable和ScheduledExecutorService内存泄漏,java,javafx,memory-leaks,runnable,scheduledexecutorservice,Java,Javafx,Memory Leaks,Runnable,Scheduledexecutorservice,我正在制作这个状态/菜单栏应用程序,它在Mac OS X的状态栏中显示当前正在播放的歌曲。要从Spotify获取播放器状态,我必须创建并执行一个AppleScript,并从中获取输出。然后使用Graphics2D中的drawString()绘制结果,该结果被设置到BuffereImage上,然后将其设置为托盘图标 整个代码由4个类组成,易于理解,可在以下位置获得: 现在开始解决问题 我的runnable似乎耗尽了我以前从未见过的记忆。每隔一秒钟,应用程序就会多使用2-3MB的RAM,如果我不这样

我正在制作这个状态/菜单栏应用程序,它在Mac OS X的状态栏中显示当前正在播放的歌曲。要从Spotify获取播放器状态,我必须创建并执行一个AppleScript,并从中获取输出。然后使用Graphics2D中的drawString()绘制结果,该结果被设置到BuffereImage上,然后将其设置为托盘图标

整个代码由4个类组成,易于理解,可在以下位置获得:

现在开始解决问题

我的runnable似乎耗尽了我以前从未见过的记忆。每隔一秒钟,应用程序就会多使用2-3MB的RAM,如果我不这样做的话,它可以达到千兆字节。到目前为止,我尝试的是刷新和处理我的所有图像和图形2D资源,刷新和关闭每个inputstream、outputstream,并销毁我在AppleScripthHelper中创建的进程对象

即使是这样,只要调用一个静态方法,RAM就会很快堆积起来

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

//update every 50ms
mainExecutor.scheduleAtFixedRate(refreshPlayingText, 0, 50, TimeUnit.MILLISECONDS);
和苹果抄写器

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

}

所以问题是,是什么吃掉了所有的公羊?为什么看起来什么都没有被垃圾收集?

您面临的不是内存泄漏

根据Java™ 进程和线程的教程()

一个进程通常有一组完整的、私有的基本运行时资源;特别是,每个进程都有自己的内存空间

您每50毫秒创建一个新进程,这很可能会占用您的可用内存


创建太多进程将导致
抖动
,您将注意到CPU性能降低。根据流程所做的工作,很可能有一种更有效的方法来实现您的目标,而不必每秒创建20个流程。

您能否发布
applescriptper#evalAppleScript
?@JacobG。好了,完成了!我懂了。因此,每秒钟运行一次进程似乎是一件更合理的事情,但当我尝试这样做时,RAM的使用量仍然增加得非常快,尽管没有以前那么快。你建议我怎么做,至少每秒钟更新一次?@Zino不幸的是,如果不知道你想要实现什么,我就不能给出很多建议。您正在运行的流程是否可以用Java完成?是的,事实上一切都是用Java完成的。代码可以在@Zino上找到,我指的是
进程本身(osascript)。哦,据我所知,很遗憾,我无法从Java调用本机Spotify进程。