在线程中运行jRuby时如何停止泄漏javaw进程?

时间:2011-08-20 01:21:48

标签: ruby groovy process jvm jruby

我正在泄漏jRuby进程,我不知道如何阻止它。我需要groovy脚本在启动jRuby之后继续运行,当主脚本死亡时我需要jRuby死。

test.groovyloop.rb

loop.rb

while( true )
   puts 'Hello from jRuby'
   sleep 1
end

test.groovy

def command = "jruby ./loop.rb"
Thread.start {
    Process process
    try {
        process = command.execute()
    }
    catch (IOException e) {
        e.printStackTrace()
        return
    }

    Runtime.runtime.addShutdownHook {
        println "Attempting to stop process"
        process.destroy()
    }

    process.consumeProcessOutput(System.out, System.err)
    process.waitFor()
}

while( true ){ println 'Hello from groovy'; Thread.sleep(1000) }

执行 groovy test.groovy

如何确保使用jRuby创建的外部javaw进程被终止?尽管将Cntrl+C发送到正在运行的应用程序会导致正在运行的groovy进程,但jRuby进程仍然存在。帮助

1 个答案:

答案 0 :(得分:0)

这应该可以解决问题,但这很难看:

基本解决方案是查看jps -lm的输出并从其中列出的PID中删除相应的进程。

new JavaProcessKiller().killAll('loop.rb')

class JavaProcessKiller {
    public void killAll(String processPattern) {
        getRunningJavaProcesses().each { String processLine ->
            if (processLine.contains(processPattern)) {
                String pidToKill = getPidFromProcessLine(processLine)
                killPid(pidToKill)
            }
        }
    }

    protected String[] getRunningJavaProcesses() {
        def output = new ByteArrayOutputStream()
        def p = ['jps', '-lm'].execute()
        p.consumeProcessOutput(new PrintStream(output), System.err)
        p.waitFor()
        return output.toString().split("\\n")
    }

    protected String getPidFromProcessLine(String line) {
        def pidPattern = /^(\d+).*$/
        def matcher = (line =~ pidPattern)
        return matcher[0][1]
    }

    protected void killPid(String pid) {
        def killCommands = [
                ['taskkill', '/F', '/PID', pid],
                ['kill', pid]
        ]

        boolean processKilledSuccessfully = false
        killCommands.each { command ->
            if (!processKilledSuccessfully) {
                try {
                    def output = new ByteArrayOutputStream()
                    def error = new ByteArrayOutputStream()
                    def process = command.execute()
                    process.consumeProcessOutput(new PrintStream(output), new PrintStream(error))
                    process.waitFor()
                    processKilledSuccessfully = true
                }
                catch (Exception e) {
                }
            }
        }
    }
}