You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.04.14 09:20:32