executing java command from script gives error even though same command from cli works fine

Question:

I’m writing a python script that amongst other things launches a jar file.

I’m using the following method to fire the java command:

 def first_launch(self):
        if self.is_initialize:
            subprocess.run(
                [f"-Xmx{self.max_memory}M", f"-Xms{self.min_memory}M", f"-jar server.jar", "nogui"],
                executable="/usr/bin/java",
                cwd=self.directory
            )
        else:
            raise Exception("Server is not initialized")

Where the var values are:

  • directory: /Users/cschmitz/Desktop/opt/minecraft/server
  • max memory: 2048
  • min memory: 1024

which should all come out to be the command:

/usr/bin/java -Xmx2048M -Xms1024M -jar server.jar nogui

When I run this command from my terminal it works fine:
running from the cli

But when I try firing it from the python subprocess I get the error:

The operation couldn’t be completed. Unable to locate a Java Runtime that supports -Xmx2048M.
Please visit http://www.java.com for information on installing Java.

I’m using an absolute path to my java executable (the same one I’m using on in the CLI) so it seems unlikely that I’d be grabbing a different version of the command (like if my cli path included a different version of the command than what my python file had access to).

I searched around for answers online and I saw where you’d see this message if you only had the java runtime and not the dev kit, but as far as I can tell I have the jdk installed (or at least I figured that if I installed open jdk I wouldn’t get just the runtime environment).

❯ java -version
openjdk version "19.0.1" 2022-10-18
OpenJDK Runtime Environment Homebrew (build 19.0.1)
OpenJDK 64-Bit Server VM Homebrew (build 19.0.1, mixed mode, sharing)

And really the fact that I can launch it just fine from the cli suggests that I have the right tools installed.

Any ideas of what I’m doing wrong or misunderstanding??

Asked By: Chris Schmitz

||

Answers:

/usr/bin/java should be the first argument, not (or at least, not just) the executable.

You only need to set executable when you need to pass a program a argv[0] that differs from the executable name; there’s no reason for them to be different here. The immediate error you get appears to be the JVM treating the basename of (which is to say, everything past the last / in) argv[0] as the name of an operational mode it’s supposed to run in; the normal operating mode is java, but there’s no mode named -Xmx2048m.

Software deciding what mode to run in based on its argv[0] is fairly common: For example, if you call executable='/bin/bash' with an argv[0] of sh, bash runs in POSIX sh compatibility mode, turning off several non-POSIX features.

As an additional issue, -jar and server.jar should be two separate arguments: -jar is specified as an argument that specifies that the next argument is the jar to run.

Thus, correct code would look more like:

subprocess.run(
    ['/usr/bin/java',
     f'-Xmx{self.max_memory}M',
     f'-Xms{self.min_memory}M',
     '-jar', 'server.jar',
     'nogui'],
    cwd=self.directory
)
Answered By: Charles Duffy
Categories: questions Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.