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) {
}
}
}
}
}
精彩评论