Where does Java's ProcessBuilder look to execute commands?
Asked Answered
T

4

6

When I execute a command using ProcessBuilder, how does it know where to look for that command? Using this hack/trick I've modified my PATH variable (verified by inspecting processBuilder.environment()) to be bad (empty, working dir, etc) but ProcessBuilder can still execute sort, echo, bash, etc. just fine. How is it doing this?!

Note: My particular development environment is OSX but this code will also run on Red Hat Enterprise Linux.

Threescore answered 20/2, 2012 at 21:27 Comment(0)
I
5

The documentation says

[...] a command, a list of strings which signifies the external program file to be invoked and its arguments, if any. Which string lists represent a valid operating system command is system-dependent. [...]

Which in essence mean that where it looks for programs to execute depends on the particular system and JVM you're running on.

I can't find a complete matrix of JVM / System behaviors, but supposedly it behaves similar to the popular shells of the system (bash for *nix and cmd for windows) i.e. it searches the directories in the PATH environment variable from left to right and executes the first executable file it finds.

Intravenous answered 20/2, 2012 at 21:29 Comment(3)
I see you found my follow up question :-P To clarify I am running on OSX and wondering if there is any way to modify where it looks.Threescore
Hmm.. beats me. Let's just wait and see if someone comes around and answers this. It seems like the ProcessBuilder must have some fallback mechanism which it checks in addition to the PATH variable.Intravenous
1.7.0_51 on OSX and I can't get it to look at PATH. Only full path in constructor worksEarring
I
1

If you want to take control of finding commands, then, well, take control of finding commands. Don't let ProcessBuilder search. Use your own code to find what you want to run, and then put an absolute pathname into the parameter to ProcessBuilder.

Ineslta answered 20/2, 2012 at 23:47 Comment(1)
I am trying to write a unit test for something that uses the ProcessBuilder to execute "sort", which wants ProcessBuilder to do the search. I was just trying to simulate sort not being found.Threescore
I
0

Unix (Linux, Mac)

For UNIX like OSes, the parent's path is searched. Source openjdk childproc.c:

/* We must search PATH (parent's, not child's) */

The flow is as follows:

  • ProcessImpl is loaded and init is called.
  • Init will call the native method to set parentPathv based on the current PATH.
  • All spawn types (i.e., fork and exec, posix_spawn, vfork and exec) will eventually flow through the area of code with the above comment.

Which means that any executable without an exact path will be searched for in parentPathv which came from the PATH value of the Java process, not the PATH that was configured as part of processBuilder.environment().

Windows

For Windows, ProcessImpl will normalize the executable in getExecutablePath and then pass it to the Win32 function CreateProcess which has these rules:

If the file name does not contain a directory path, the system searches for the executable file in the following sequence:

1. The directory from which the application loaded.
2. The current directory for the parent process.
3. The 32-bit Windows system directory. Use the GetSystemDirectory function to get the path of this directory.
4. The 16-bit Windows system directory. There is no function that obtains the path of this directory, but it is searched. The name of this directory is System.
5. The Windows directory. Use the GetWindowsDirectory function to get the path of this directory.
6. The directories that are listed in the PATH environment variable. Note that this function does not search the per-application path specified by the App Paths registry key. To include this per-application path in the search sequence, use the ShellExecute function.

CreateProcess also receives the PATH from the Java process, not what is configured as part of processBuilder.environment().

Inquiline answered 12/9 at 17:7 Comment(0)
J
0

ProcessBuilder likely finds commands through:

  1. Built-in shell commands
  2. Default system paths (/usr/bin, /bin, etc.)
  3. Internal Java implementation details Inherited JVM environment
  4. settings OS-specific command resolution mechanisms

These factors can allow command execution even with a modified PATH. To determine the exact method, you'd need to use system tracing tools or examine the Java source code for your specific runtime.

Jacquelynejacquelynn answered 12/9 at 18:0 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.