I have a graphical JavaFX application that is launching a secondary child process using Javaw.exe. Javaw.exe is chosen because I do not want a console window to be visible. After a short amount of time the subprocess spontaneously spawns a blank console window.
Shown here is a screenshot of the situation when it occurs. I know which process it is. Its process with PID 10972.
I have never seen a javaw.exe console appear before so I don't even know where to begin looking to potentially find the root cause.
Right now my suspicions are that some native code is causing the console window to appear. This app does indeed load some RTI DDS dlls and is executing an RTI recording service instance via those dlls. Given that that is my suspicion, I am looking for some suggestions on some things to check. I really don't even know where to begin looking. I did try running this app with java.exe to see if there was any strange console output that could be coming from native code that I'm not aware of but I did not see any.
This has been a chronic issue for some time for my software package and am just looking for some direction. Has anyone ever seen this kind of thing happen before?
Here's a photo of the process tree showing the problematic console window under the javaw.exe app.
Below is the code I use to launch the child javaw.exe process. In this scenario, logging is disabled and therefore swallowProcessOutput
gets executed. Its worth noting that I have 4 other subprocesses that are called in the same manner with logging disabled and they never have a javaw.exe console window appear.
You might ask why I am consuming output for a javaw.exe process that shouldn't have any to begin with and I don't really have a good response to that at the current time. All I know is that I had issues with subprocesses hanging if I did not consume the console output during development several years ago. I do not suspect this is the cause of the console window appearing anyways, but figured it should be mentioned.
I am really just looking for some kind of direction on how to go about troubleshooting this. Any suggestions would be helpful on trying to track down what could be causing this whether that's 3rd party debugging tools, windows tricks, or whatever.
System info
Microsoft Windows 10 Enterprise 10.0.17763
openjdk version "19.0.36" x86
/**
* Executes the command that will launch this server application. This method will start a new instance of the
* server application each time it is called.
*/
public void launch()
{
Map<String, String> envMap = new HashMap<>();
environment.variables.forEach(eVar -> envMap.put(eVar.varName, eVar.varValue));
final File workingDir = new File(workingDirectory);
if ((!workingDir.exists() || !workingDir.isDirectory()) && !workingDir.mkdirs())
{
LOG.error("Unable to create working directory for app {}", this);
}
launcher = new ProcessBuilder(commandmandArguments).directory(workingDir);
launcher.environment().putAll(envMap);
try
{
if (!commandmandArguments.isEmpty())
{
LOG.info("Launching server app {} with command {}", getName(), String.join(" ", commandmandArguments));
Process launchedAppProcess = launcher.start();
if (logging.enabled)
{
LOG.info("Output will be logged for server application {}", getName());
final String threadName = getName().contains(".") ? getName().split("\\.")[0] : getName();
Utils.logProcessOutput(launchedAppProcess, LogManager.getLogger("company.logging." + threadName), logging.lineExclusions);
}
else
{
LOG.info("Output will not be logged for server application {}", getName());
Utils.swallowProcessOutput(launchedAppProcess); /* We need to read the output or else the app may hang if using javaw.exe */
}
}
else
{
LOG.warn("Command not found for server app {}. App was not launched.", getName());
}
}
catch (Exception e)
{
LOG.error("Error launching server app {}", name, e);
}
finally
{
try
{
LOG.info("Pausing for {} milliseconds before launching the next server app", postLaunchPauseMS);
Thread.sleep(postLaunchPauseMS);
}
catch (InterruptedException e)
{
LOG.warn("Post launch pause of app {} was interrupted", name);
Thread.currentThread().interrupt();
}
}
}
/**
* Reads a given process's output and does nothing with it
*
* @param p process to swallow output
*/
public static void swallowProcessOutput(Process p)
{
ScheduledExecutorService loggerService = Executors.newScheduledThreadPool(2, DAEMON_THREAD_FACTORY);
loggerService.schedule(() ->
{
try (Scanner sc = new Scanner(p.getInputStream()))
{
while (!p.isAlive())
{
//noinspection BusyWait
Thread.sleep(250);
}
while (sc.hasNextLine() && p.isAlive())
{
sc.nextLine(); /* Do nothing */
}
}
catch (InterruptedException i)
{
Thread.currentThread().interrupt();
}
catch (Exception e)
{
LOG.catching(e);
}
}, 0, TimeUnit.MILLISECONDS);
loggerService.schedule(() ->
{
try (Scanner sc = new Scanner(p.getErrorStream()))
{
while (!p.isAlive())
{
//noinspection BusyWait
Thread.sleep(250);
}
while (sc.hasNextLine() && p.isAlive())
{
sc.nextLine(); /* Do nothing */
}
}
catch (InterruptedException i)
{
Thread.currentThread().interrupt();
}
catch (Exception e)
{
LOG.catching(e);
}
}, 0, TimeUnit.MILLISECONDS);
}
I tried launching the app with javaw.exe but the console window appears after an indeterminate amount of time. I tried launching the app with java.exe to see if there was any console output coming from native code but no additional output could be identified. If I spawn a console intentionally it makes knowing when the issue occurs pretty much impossible since the issue itself IS the console window. I am expecting no console window to ever appear when using Javaw.exe.
Edit 1: Tried checking for calls to AllocConsole using procmon as suggested by Botje but it yielded no results even after the console appeared.