본문으로 건너뛰기
안동민 개발노트 아이콘

안동민 개발노트

본문 시작
1장 : Java 설치와 첫 프로그램

처음 만나는 Java 오류

컴파일 오류, 클래스 탐색 오류, 실행 중 오류를 각각 재현하고 메시지에서 고칠 위치를 찾습니다.

오류 메시지는 실패 그 자체가 아니라 어느 단계까지 성공했는지 알려 주는 기록입니다.

먼저 컴파일 중인지, 클래스를 찾는 중인지, main을 실행한 뒤인지를 구분하면 고칠 위치가 좁아집니다.


컴파일 오류: 문법을 읽을 수 없음

src/BrokenSyntax.java를 다음처럼 저장합니다.

출력문 끝의 세미콜론을 일부러 빠뜨렸습니다.

src/BrokenSyntax.java — 일부러 실패하는 파일
public class BrokenSyntax {
    public static void main(String[] args) {
        System.out.println("semicolon missing")
    }
}
javac -d out src/BrokenSyntax.java
src\BrokenSyntax.java:3: error: ';' expected
        System.out.println("semicolon missing")
                                               ^

파일과 3번째 줄이 표시되고 컴파일러가 예상한 기호가 나옵니다.

세미콜론을 추가한 뒤 다시 컴파일합니다.

컴파일에 실패한 상태에서는 새 BrokenSyntax.class가 만들어지지 않습니다.


클래스 탐색 오류: 컴파일 결과를 못 찾음

Hello를 정상 컴파일한 뒤 클래스 경로를 빼고 실행합니다.

javac -d out src/Hello.java
java Hello
Error: Could not find or load main class Hello
Caused by: java.lang.ClassNotFoundException: Hello

out/Hello.class는 존재하지만 현재 폴더에서 찾았기 때문에 실패했습니다.

탐색 시작 폴더를 고칩니다.

java -cp out Hello

이 오류에서는 소스 코드를 고칠 필요가 없습니다.

컴파일 결과의 위치와 실행 명령을 고쳐야 합니다.


실행 중 오류: main에 들어간 뒤 실패

다음 파일은 문법상 올바르므로 컴파일됩니다.

하지만 정수를 0으로 나누는 문장을 실행할 때 더 진행할 수 없습니다.

src/RuntimeFailure.java — 일부러 실패하는 파일
public class RuntimeFailure {
    public static void main(String[] args) {
        System.out.println("before");
        System.out.println(10 / 0);
        System.out.println("after");
    }
}
javac -d out src/RuntimeFailure.java
java -cp out RuntimeFailure
before
Exception in thread "main" java.lang.ArithmeticException: / by zero
    at RuntimeFailure.main(RuntimeFailure.java:4)

before가 출력됐으므로 JVM은 클래스를 찾고 main에도 진입했습니다.

마지막 줄의 파일명과 줄 번호는 실패한 문장을 가리킵니다.

after는 오류 뒤에 있으므로 실행되지 않습니다.

예외의 종류와 복구 방법은 ch12에서 배웁니다.

지금은 컴파일 오류와 달리 .class가 정상 생성됐고 실행 도중 실패했다는 점만 구분합니다.


이름 오류도 단계가 다르다

공개 클래스와 파일 이름이 다르면 컴파일 단계에서 실패합니다.

src/WrongName.java — 일부러 실패하는 파일
public class DifferentName {
    public static void main(String[] args) {
        System.out.println("not compiled");
    }
}

반대로 클래스는 컴파일됐지만 실행 가능한 main이 없으면 실행 단계에서 시작점을 찾지 못합니다.

src/NoMain.java — 컴파일은 되는 파일
public class NoMain {
    public static void print() {
        System.out.println("no entry point");
    }
}

print는 일반 메서드이고 자동으로 실행되지 않습니다.

java -cp out NoMainmain을 찾을 수 없다는 메시지를 냅니다.


오류를 읽는 순서

  1. 실행한 명령이 javac인지 java인지 확인합니다.
  2. 첫 오류의 종류와 메시지를 읽습니다.
  3. 표시된 파일과 줄을 찾습니다.
  4. 그 줄만 보지 말고 바로 앞의 괄호·중괄호·세미콜론도 확인합니다.
  5. 하나를 고친 뒤 같은 명령을 다시 실행합니다.

뒤에 이어지는 수십 개 오류가 첫 문법 오류 때문에 생길 수 있습니다.

한꺼번에 모든 줄을 바꾸지 말고 첫 오류부터 처리합니다.


연습 문제

다음 증상을 컴파일, 클래스 탐색, 실행 중 오류로 분류하고 첫 확인 대상을 적으세요.

  • ';' expected
  • ClassNotFoundException: Hello
  • ArithmeticException: / by zero
  • 파일을 수정했는데 이전 문장이 출력됨

마지막 증상은 오류 메시지가 없지만 오래된 .class를 실행한 경우입니다.

소스를 저장한 뒤 javac를 다시 실행했는지 확인합니다.