Programming/Java

[JAVA] System.console()은 Intellij 환경에서 지원하지 않습니다.

R.i.c.K.y 2023. 12. 15. 01:57

TroubleShooting

자바를 공부하던 중, 표준 입출력 스트림 중에서 코드를 작성하다 런타임 에러가 발생했다.

import java.io.*;

class BRRead {
	public static void main(String[] args) throws IOException {
    	char c;
        BufferedReader br = new BufferedReader(new InputStreamReader(System.in, System.console().charset()));
    }
    ...
}

 

Intellij 환경에서 실행했다.

하지만 실행 버튼을 누르자 다음과 같은 에러가 발생했다.

Exception in thread "main" java.lang.NullPointerException: Cannot invoke "java.io.Console.charset()" because the return value of "java.lang.System.console()" is null
at lecture12.StreamStudy.main(StreamStudy.java:7)

 

위 에러를 보고, 처음 든 생각은 "아! 메인함수 인자를 주지 않았구나..!" 였다.

 

첫번째 방법 : Argument를 입력해주기

따라서, Intellij의 Edit Configurations를 통해 메인 함수에 인자 값을 주기로 판단했다.

CLI Argument에 임의 문자열 넣어주기

기대를 품고 다시 실행버튼을 클릭했지만, 처참히 실패..! 심지어 에러메세지도 동일하게 나왔다..

이에 콘솔함수에 대해 Documentation을 읽어본 결과, 애초에 IDE 상에서는 안된다는 것을 깨달았다.
또한 메인함수의 인자값을 읽는 것이 아닌, 런타임 중 유저로부터의 inputStream을 읽어들이는 과정이라는 것을 깨달았다.

 

Solution

아래는 System.console()에 적힌 Documentation 일부분을 발췌한 글이다.

Whether a virtual machine has a console is dependent upon the underlying platform and also upon the manner in which the virtual machine is invoked. If the virtual machine is started from an interactive command line without redirecting the standard input and output streams then its console will exist and will typically be connected to the keyboard and display from which the virtual machine was launched. If the virtual machine is started automatically, for example by a background job scheduler, then it will typically not have a console.

 

요약하면, System.console()은 문자 기반 콘솔 디바이스에 접근하는 방법이라서, 시스템에 해당 콘솔이 있어야 동작하는 함수다. 예를 들어 로컬 상의 터미널에서 javac, java 명령어를 통해 컴파일을 했다면 정상적으로 동작할 것이다.

CLI에서 실행해본 결과 잘 나온다.

실제로 로컬 터미널에서 실행한 결과 기가 막히게 잘되는 것을 확인했다.

 

결론은, 콘솔에 접근할 수 있는 환경에서만 System.console()이 동작한다는 것이다.
함수명이 console이니 콘솔이 있어야 한다는 것은 알겠는데, 문제는 해당 환경에 콘솔이 있는지를 어떻게 아느냐이다.

 

현재 환경에서 콘솔이 있는지 유무 체크

이에 대한 해답 역시 위의 Documentation에 적혀있다. 위에서 기재한 발췌글을 다시 한 번 읽어보자.

If the virtual machine is started from an interactive command line without redirecting the standard input and output streams then its console will exist and will typically be connected to the keyboard and display from which the virtual machine was launched. If the virtual machine is started automatically, for example by a background job scheduler, then it will typically not have a console.

 

즉, 표준 입출력 스트림으로 Redirecting 하는 과정 없이 JVM과 콘솔 입출력이 직접 연결되어있으면 된다.

Virtual JVM이더라도 직접 연결되어있기만 한다면 문제없다.
중요한 건 바로 다음 줄이다. 가상 머신이 백그라운드 작업 스케줄러에 의해 자동으로 시작한다면 이것은 콘솔을 이용하지 않은 스트림이기 때문에 System.console()이 동작하지 않는다.
그리고, Intellij를 포함한 대부분의 IDE는 후자의 방식으로 실행되기 때문에 System.console() 메서드를 이용할 수 없는 것이다.

 

결론

Intellij에선 System.console() 이용 불가하다.
굳이 실행시키고 싶으면 console 없이 사용하면 된다.