2011-08-20 46 views
1

我泄漏jRuby進程,我不知道如何阻止這個。在啓動jRuby之後,我需要groovy腳本繼續前進,當主腳本死亡時我需要jRuby去死。如何在線程中運行jRuby時停止泄漏javaw進程?

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到正在運行的應用程序會導致正在運行的常規進程,jRuby進程仍然存在。幫幫我?

+0

常規有沒有Process.kill? – rogerdpack

+0

它並沒有真正殺死這個進程。 –

+0

如果是windows,我不得不求助於調用taskkill,就像接受的答案一樣(jruby的Process.kill也不起作用) – rogerdpack

回答

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