使用javaw.exe启动JavaFX子进程时随机出现空白控制台窗口的排查求助
javaw.exe启动JavaFX子进程时随机出现空白控制台窗口的排查求助
我遇到一个长期困扰的棘手问题,想请大家给点排查方向:
我有一个JavaFX图形化应用,用javaw.exe启动了一个子进程——选javaw.exe就是为了避免显示控制台窗口,但过一段时间后,这个子进程会突然弹出一个空白的控制台窗口。我能定位到对应的进程(PID 10972),但完全不知道从何入手找根因。
我怀疑是某些原生代码导致的,因为这个应用确实加载了RTI DDS的DLL,并且通过这些DLL运行一个RTI录制服务实例。但我真的不知道该从哪些地方检查,目前毫无头绪。
已尝试的排查动作
- 换成
java.exe启动应用,想看看有没有原生代码输出的异常控制台内容,但什么也没看到 - 用ProcMon检查
AllocConsole调用,即使控制台出现后也没找到相关结果
相关信息
进程结构
控制台窗口是挂在javaw.exe进程下面的,进程树能清晰看到这个层级关系(javaw.exe节点下直接关联着那个有问题的控制台窗口对应的进程)
子进程启动代码
我用来启动子javaw.exe进程的代码如下,其中日志关闭时会执行swallowProcessOutput方法——另外提一句,我还有4个同样方式启动的子进程(日志也关闭),但它们从来没出现过控制台窗口:
/** * 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(command.commandArguments).directory(workingDir); launcher.environment().putAll(envMap); try { if (!command.commandArguments.isEmpty()) { LOG.info("Launching server app {} with command {}", getName(), String.join(" ", command.commandArguments)); 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("com.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); }
系统环境
Microsoft Windows 10 Enterprise 10.0.17763 openjdk version "19.0.36" x86
求助
有没有人遇到过类似的情况?能不能给我一些排查建议?比如可以用什么第三方调试工具、Windows的排查技巧,或者针对RTI DDS的检查点?真的很需要方向,这个问题已经困扰我们很久了。
备注:内容来源于stack exchange,提问作者Jake Henry
相关产品推荐
相关产品推荐

