[Java] 주석은 컴파일 단계에서 어떻게 될까?
Language/Java

[Java] 주석은 컴파일 단계에서 어떻게 될까?

주석을 많이 달면 프로그램의 성능에 저하가 생길까? 이 부분에 대한 궁금증을 해결하기 위해 바로 실습을 해보았다. 일단 자바 코드가 컴파일되었을 때 주석이 남는지 확인을 해야 한다.

 

// Test.java
public class Test {

    public static void main(String[] args) {
        //  this is comment. do you see?
        double a = 10/3;
        System.out.println(a);
    }
}

자바 코드에서 "this is comment. do you see?" 부분이 바이트 코드에서 보이는지 확인을 하기 위해 먼저 컴파일을 시도한 후, 역 어셈블러(javap)를 이용하면 바이트 코드를 확인할 수 있다.

// 컴파일
javac Test.java

// 역어셈블
javap -c Test.class

바이트 코드를 확인해보면 주석이 남아 있지 않다. 그렇다면 컴파일러는 주석을 무시하고 진행하는 것이니 주석이 아무리 많이 달려도 컴파일러에게 무리가 가지 않겠다고 생각했다.

Test.java 의 바이트 코드

하지만 한글로 주석을 사용하면 컴파일 과정에서 에러가 발생한다. 분명 바이트코드에 주석이 없기 때문에, 컴파일러는 주석을 무시하고 지나가니 주석에 어떤 문자가 담겨도 문제가 없어야 한다. 이에 대한 답을 찾기 위해 에러 문을 보면 인코딩에 대한 에러이다. 컴파일러는 주석을 인코딩하는 것인가?

한글로 된 주석을 사용한 Test.java 를 컴파일 시 발생한 에러문

그럼 여기서 3가지의 사실을 알 수 있다.

  • 컴파일러는 주석을 무시하지 않고 읽는다.
  • 컴파일러는 주석을 인코딩하려고 시도한다.
  • 컴파일러는 주석을 인코딩한 후, 무시한다.

컴파일러는 자바 코드를 바이트 코드로 변환하기 전에 Lexical Translations 를 수행한다. 코드를 토큰 시퀀스로 변환하는 과정인데, 이때 코드에서 유니코드 문자를 이스케이프로 변환한 후 아스키코드로 인코딩을 처리하여 토큰 시퀀스로 변환한다. 그 후, 공백과 주석을 삭제하기 때문에 컴파일 과정에서 위와 같이 인코딩 에러가 발생했던 것이다.

그럼 굳이 이스케이프 문자로 변환하는 과정이 필요할까? 그에 대한 답은 아직 찾지 못했는데, 이 글에서는 실수라고 보는 사람도 있고, 의도한 것이라고 보는 사람도 있다.

 

어쨌든, 결론은 컴파일러가 주석을 변환하는 과정이 있기 때문에 주석의 양과 컴파일 시간이 관계가 전혀 없다고 말할 순 없지만, 단순히 인코딩하는 것이기 때문에 엄청나게 영향을 줄 것 같지 않다.

 

유니코드 문자를 이스케이프로 변환을 확인해볼 겸 재미있는 테스트를 해봤다.

public class Test {

    public static void main(String[] args) {
        //the below comment will be executed
        // \u000d System.out.println("Java comment is executed!!");
    }
}

유니코드 문자 \u000d이 이스케이프 문자로 변환되며 \n(개행)의 의미를 가지게 되었다. 그래서 println 부분이 주석이 해제되며 코드가 실행된 것이다.

 

주석이 실행된다!

 

'Language > Java' 카테고리의 다른 글

컴파일에 대해서  (0) 2023.01.15
[JAVA] == 과 equals 비교  (0) 2022.07.24
[Java] 로그 구하기  (0) 2022.02.14
[Java] 스택 사용하기(Stack Class)  (0) 2022.02.08
[Java] int 타입을 이진수로 바꾸는 방법  (0) 2022.02.06