Я разработал приложение C++ и хочу вызвать его из моего приложения Java. Для этого я использую ProcessBuilder:
C++
Java
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;
Вот как я читаю вывод процесса:
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(); }
Я получаю:
exit code -1073741819 (0xC0000005)
Это, кажется, означает The application was unable to start correctly, и я даже не получаю исходную печать консоли авторского права в начале кода EXE.
The application was unable to start correctly
EXE
Если вместо этого я запускаю EXE на CMD, он будет работать успешно, даже если я передал точно такие же аргументы. Почему это происходит? Я скомпилировал код для Linux и Mac OS X, но оба они отлично работают в своих операционных системах через Java и Terminal. Упомянутый код выхода 0xC0000005 происходит только на Windows, а не только на моем ПК. 2 других пользователей также наблюдали эту проблему. Иногда Windows EXE все равно запускается с Java, хотя это еще более странно.
CMD
Linux
Mac OS X
Terminal
0xC0000005
Windows
Флаги компиляции C++, которые я использую:
# /MD Causes the application to use the multithread-specific and DLL-specific version of the run-time library: # https://docs.microsoft.com/en-us/previous-versions/2kzt1wy3(v=vs.140) # /Ox (Full Optimization): https://docs.microsoft.com/en-us/previous-versions/59a3b321(v=vs.140) # /GL (Whole Program Optimization): https://docs.microsoft.com/en-us/previous-versions/0zza0de8(v=vs.140) # /cgthreads (Code Generation Threads): https://docs.microsoft.com/en-us/previous-versions/dn631956(v=vs.140) # /MP (Build with Multiple Processes): https://docs.microsoft.com/en-us/previous-versions/bb385193(v=vs.140) # /fp (Specify Floating-Point Behavior): https://docs.microsoft.com/en-us/previous-versions/e7s85ffb(v=vs.140) # /Gw (Optimize Global Data): https://docs.microsoft.com/en-us/previous-versions/dn305952(v=vs.140) # /GS (Buffer Security Check): https://docs.microsoft.com/en-us/previous-versions/8dbf701c(v=vs.140) # /favor (Optimize for Architecture Specifics): https://docs.microsoft.com/en-us/previous-versions/ms173505(v=vs.140) # /Qpar (Auto-Parallelizer): https://docs.microsoft.com/en-us/previous-versions/hh923900(v=vs.140) # /EH (Exception Handling Model): https://docs.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}")
Оказывается, что переданные аргументы не были одинаковыми, потому что Java интерпретирует пустую строку как аргумент в Windows.Поэтому он индексировал массив аргументов за пределами границ и по-прежнему отказывался печатать что-либо еще до того, как произошла ошибка памяти, которая не является интуитивно понятной.