I developed a C++
application and I want to call it from my Java
application. For this I'm using ProcessBuilder
:
ProcessBuilder processBuilder = new ProcessBuilder(command);
processBuilder.redirectErrorStream(true);
Process process = processBuilder.start();
String processOutput = readFromProcess(process);
val exitCode = process.waitFor();
if (exitCode != 0)
{
// Exception
}
return processOutput;
Here is how I read the process' output:
public static String readFromProcess(Process process) throws IOException
{
StringBuilder stringBuilder;
String lineSeparator = lineSeparator();
try (BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(process.getInputStream())))
{
stringBuilder = new StringBuilder();
String line;
while ((line = bufferedReader.readLine()) != null)
{
stringBuilder.append(line);
stringBuilder.append(lineSeparator);
}
}
return stringBuilder.toString().trim();
}
I'm getting:
exit code -1073741819 (0xC0000005)
This seems to mean The application was unable to start correctly
and I do not even get the initial copyright console print at the beginning of the EXE
's code.
If I run the EXE
on CMD
instead it will run successfully even though I passed exactly the same arguments. Why does this happen? I compiled the code for Linux
and Mac OS X
but both of them run fine on their respective operating systems via Java
and the Terminal
. The mentioned exit code 0xC0000005
only occurs on Windows
and not just on my PC. 2 other users observed this issue as well. Sometimes the Windows
EXE
would still run from Java
though which is even more odd.
The C++
compilation flags I use are:
# /MD Causes the application to use the multithread-specific and DLL-specific version of the run-time library:
# https://learn.microsoft.com/en-us/previous-versions/2kzt1wy3(v=vs.140)
# /Ox (Full Optimization): https://learn.microsoft.com/en-us/previous-versions/59a3b321(v=vs.140)
# /GL (Whole Program Optimization): https://learn.microsoft.com/en-us/previous-versions/0zza0de8(v=vs.140)
# /cgthreads (Code Generation Threads): https://learn.microsoft.com/en-us/previous-versions/dn631956(v=vs.140)
# /MP (Build with Multiple Processes): https://learn.microsoft.com/en-us/previous-versions/bb385193(v=vs.140)
# /fp (Specify Floating-Point Behavior): https://learn.microsoft.com/en-us/previous-versions/e7s85ffb(v=vs.140)
# /Gw (Optimize Global Data): https://learn.microsoft.com/en-us/previous-versions/dn305952(v=vs.140)
# /GS (Buffer Security Check): https://learn.microsoft.com/en-us/previous-versions/8dbf701c(v=vs.140)
# /favor (Optimize for Architecture Specifics): https://learn.microsoft.com/en-us/previous-versions/ms173505(v=vs.140)
# /Qpar (Auto-Parallelizer): https://learn.microsoft.com/en-us/previous-versions/hh923900(v=vs.140)
# /EH (Exception Handling Model): https://learn.microsoft.com/en-us/previous-versions/1deeycx5(v=vs.140)
# DNDEBUG: Disable assert macro evaluation
set(OPTIMIZATIONS "/MD /Ox /GL /cgthreads8 /MP8 /fp:fast /Gw /GS- /favor:INTEL64 /Qpar /EHs /EHc- /DNDEBUG")
set(CMAKE_CXX_FLAGS_RELEASE "${OPTIMIZATIONS}")
It turns out the passed arguments weren't the same because Java
interprets an empty string as no argument on Windows
. Therefore, it indexed the array of arguments out of bounds and still refused to print anything from before the memory error even happened which is non-intuitive.