开发者

How do I stop leaking javaw processes when running jRuby in a thread?

I'm leaking jRuby processes, and I don't know how to stop this. I need the groovy script to keep going after launching jRuby, and I need jRuby to die when the main script dies.

test.groovy, loop.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) }

Execute groovy test.groovy

How do I make sure that the external javaw process I create with jRuby is killed? Even though sending Cntrl+C to the running application kills t开发者_Go百科he running groovy process, the jRuby process sticks around. Help?


This should do the trick, but it's ugly:

The basic solution is to look at the output of jps -lm and kill the appropriate process from the PIDs listed there.

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) {
                }
            }
        }
    }
}
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜