【问题标题】:`System.console()` returns `null` if executed from `gradle run`如果从 `gradle run` 执行,`System.console()` 返回 `null`
【发布时间】:2016-09-18 04:29:48
【问题描述】:

我有这个简单的 Java 程序:

package me.fornever.javaterminal;
public class Main {
    public static void main(String[] args) {
        System.out.println("Console: " + System.console());
    }
}

还有这个简单的build.gradle

apply plugin: 'java'
apply plugin: 'application'
mainClassName = 'me.fornever.javaterminal.Main'

当我使用gradle --no-daemon run 执行它时,我得到以下输出:

Console: null

如果我从终端通过gradle jar; java -cp '.\build\libs\java-terminal.jar' me.fornever.javaterminal.Main 执行它,我会得到以下信息:

Console: java.io.Console@3d4eac69

我知道当父进程使用标准输出重定向时,System.console() 可能会返回null。是否有一些 Gradle 选项可以禁用重定向并使控制台对我的程序完全可用?

我正在为 Java 开发一个终端库,因此我想在没有 Gradle 干预 stdin/stdout/stderr 的情况下运行我的测试和可执行文件。

请注意System.console()null 不是唯一的问题,而是最明显的问题。实际上,我想从gradle run 执行的程序中访问WinAPI WriteConsoleW 函数,由于System.console()null 的相同原因,我无法使用此函数。因此,如果此选项可用,我真的需要在 Gradle 中禁用输出重定向。

另外请注意,该问题与Gradle build null console object 不同,因为该问题询问如何在Gradle 脚本中使用System.console(),而不是在gradle run 调用的Java 程序中;我相信他们在这件事上的工作方式不同,因为这两个答案都不起作用或不适用于我的情况。

【问题讨论】:

  • 你如何测试一个使用console()的程序?你不能给它发送测试输入,你也不能验证输出,那你在测试什么?
  • @Andreas 首先我测试它是否正常工作并且没有抛出任何异常。第二种选择是使用一些依赖于平台的 API,如 win32 ReadConsoleOutput 或包装器,如 winpty。我正在为 Windows 控制台编写一个包装库,所以使用平台相关的解决方案是可以的。
  • 那么当您进行网络搜索时,您发现了什么?你找到这个重复的问题了吗?
  • 不,链接的答案对我不起作用。我特别提到我正在运行gradle --no-daemon run,它仍然不起作用。
  • 我也有同样的问题。我在某处读到,在运行任务中包含standardInput = System.in 会使其工作,但它对我不起作用。无论如何,有些人报告说这对他们有用。

标签: java gradle console


【解决方案1】:

为了使java.io.Console 可用,子进程的标准输入和标准输出必须指向 Linux/macOS/Unix 终端或 Windows 控制台。安排它的最简单方法是从已经以这种方式设置的父进程继承标准输入和标准输出。但是,Gradle (GRADLE-3292) 存在一个已知限制,即 JavaExec 任务类型不支持让子进程继承父进程的输入/输出流。

如果 Gradle JavaExec 任务类型得到增强以支持 stdin/stdout 继承,那么这可以用于 gradle --no-daemon run

让它与 Gradle 守护进程一起工作要复杂得多,并且可能涉及特定于平台的代码来操作伪终端或调用 Windows 控制台 API。

【讨论】:

    猜你喜欢
    • 2011-05-11
    • 1970-01-01
    • 2021-04-16
    • 1970-01-01
    • 2014-12-05
    • 1970-01-01
    • 2023-03-31
    相关资源
    最近更新 更多