JoeG
JoeG

Reputation: 7652

This Groovy code is not working when run under Java 8

Strange behavior here. The Groovy snippet below (executed by Java from a jarfile) is used to start a console program that always must be running. It starts it up perfectly when running under Java 1.7.0_80 and Groovy 2.3.10. The reason it uses the 'envList' is that is subsequently called by ANOTHER program if it is detected that the console application has gone away. This second part also works fine with those versions of Java and Groovy.

List envList = ['JVM_GC_OPTS=', 'JVM_SIZE_PERM=', 'JVM_SIZE=']
String workingDir = "${someDir}/console/bin"
def console = ['/bin/bash', '-c', 
    "${someDir}/console/bin/console.sh start"].execute(envList, new File(workingDir))
console.waitForOrKill(30000)

When Java is upgraded to 1.8.0_65 the first usage no longer works. However, if started by hand (i.e. running the shell script manually), then the second usage can be tested - THAT works just fine. I can not figure out how to see the output of the shell script from the program usage. As it works from the command line, I don't really have any error information - all of the various log files are clean without ERROR or Exceptions.

Really stuck on this issue, although I am not expecting definitive answer, any suggestions on what to try or how to proceed would help me immensely.

Upvotes: 1

Views: 722

Answers (1)

JoeG
JoeG

Reputation: 7652

I have something working now. One possibly important factor I didn't mention in the original question is that while I am trying to run with Java 8, the code is compiled elsewhere with Java 7.

The solution seems very brittle and I don't understand why it works and other variants do not....

First though, this (error processing code removed) works:

def executeOnShell(String command) {
    return executeOnShell(command, new File(System.properties.'user.dir'))
}

def executeOnShell(String command, File workingDir) {
    def process = new ProcessBuilder(addShellPrefix(command))
                                      .directory(workingDir)
                                      .redirectErrorStream(true)
                                      .start()
    StringBuilder sout = new StringBuilder()
    StringBuilder serr = new StringBuilder()
    process.consumeProcessOutput(sout, serr)
    process.waitForOrKill(30000)
    sout.toString()
  }

def addShellPrefix(String command) {
    def commandArray = new String[3]
    commandArray[0] = "sh"
    commandArray[1] = "-c"
    commandArray[2] = command
    return commandArray
}

What is brittle in this solution?

  • If I call the second executeOnShell method with a workingDir other than the defaulted one, it fails. Both ways work fine under Java 7.
  • I could never get the 'more groovy' approach outlined in the original question to work. Still wondering about that.
  • If 'consumeProcessOutput' is not invoked (and use any alternative mechanism) it also does not work.

If anyone cares to explain any of this, I think many will be interested. In any event, at least a workaround is documented here.

Upvotes: 0

Related Questions