ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • [Java] javac, java 명령어
    java/Java Command 2022. 11. 20. 20:57

    https://docs.oracle.com/en/java/javase/11/tools/javac.html#GUID-AEEC9F07-CB49-4E96-8BC7-BCC2C7F725C9

     

    Tools Reference

    You can use the javac tool and its options to read Java class and interface definitions and compile them into bytecode and class files.

    docs.oracle.com

    IDE를 쓰다보니, classpath에 대한 이해가 부족하였으며, 프로젝트 구조에 대한 지식도 부족함을 느껴서 직접 컴파일과 실행작업을 진행해보기로 하였는데, 진행도중 -classpath(-cp)옵션, -sourcepath옵션, 패키지 구조와 디렉토리 구조에 대해 겪은 삽질에 대해 정리하였다.(java 11기준)

     

     


    소스 파일을 컴파일하기 전에 기본적인 javac명령어에 대해 적어본다.

     

    1. javac [-옵션1 옵션값 -옵션2 옵션값 ... -옵션n 옵션값] 파일1.java

    -> 명령어를 입력한 디렉토리에 존재하는 파일1.java를 명시된 옵션으로 컴파일 한다.

     

    2. javac [-옵션1 옵션값 -옵션2 옵션값 ... -옵션n 옵션값] 파일1.java 파일2.java

    -> 명령어를 입력한 디렉토리에 존재하는 파일1.java와 파일2.java를 명시된 옵션으로 컴파일 한다.

     

    3. javac [-옵션1 옵션값 -옵션2 옵션값 ... -옵션n 옵션값] *.java

    -> 명령어를 입력한 디렉토리에 존재하는 모든 java파일을 명시된 옵션으로 컴파일 한다.

     

    위와 같이 javac명령어를 입력했다해도 컴파일러에 의해 명령어에 입력한 소스 파일들만 컴파일되는 것이 아니라 해당 소스 파일이 import하는 것들이 자동으로 컴파일 될 수도 있고 안될 수도 있다. 이것이 javac의 -classpath옵션과 -sourcepath옵션이다.


    javac의 옵션

     

    A.java를 컴파일하려고 할때 A.java에 관련된 파일들이 필요할 수 있다.(import)

    컴파일러는 A.java 컴파일에 필요한 파일들을 class파일을 통해 찾아 A.java를 컴파일할 수 있다.

    컴파일러는 A.java 컴파일에 필요한 파일들을 java파일로 찾아 해당 java파일들도 컴파일하면서 A.java를 컴파일 할수 있다.

     

     

    javac A.java 가정시

     

    -classpath(-cp)옵션

    A.java 컴파일시 관련된 class파일을 어디서 찾겠다라고 명시. 여러 경로를 지정가능

    미정의 -> 명령어를 입력한 현재 디렉토리 하위에서 A.java에 필요한 모든 클래스 파일을 찾는다.

     

    -sourcepath 옵션

    A.java 컴파일시 관련된 java파일을 어디서 찾겠다라고 명시

    미정의 -> classpath옵션에 해당하는 경로들에서도 java파일 탐색이 포함된다.

     

    -d 옵션

    A.java 컴파일 과정에서 생성된 모든 class파일들을 어디에 저장할 것인가 명시

    참조되는 class파일이 없어서 java소스 파일이 참조되야 할때 해당 java파일들도 자동으로 컴파일될 수 있다.


    A.java

    package a;
    
    public class A{
    	public static void print(){
    		System.out.println("A");
    	}
    }

    현재 디렉토리(root)에 존재하는 A.java를 컴파일한다.

    cp 옵션 미정의

    -> A.java에 컴파일에 관련된 클래스 파일을 root 디렉토리 하위(명령어 입력한 디렉토리)에서 찾는다

    sourcepath 옵션 미정의

    -> A.java에 컴파일에 관련된 클래스 파일이 없을 때 관련된 소스 파일을 classpath옵션(명령어 입력한 디렉토리)에서 찾는다.

    A.java에는 현재 참조가 필요한 것들이 존재하지 않으므로 cp옵션과 sourcepath옵션을 아무렇게 줘도 문제가 되지 않는다.


    Main.java

    import a.A;
    
    public class Main{
    	public static void main(String[] args){
    		new A().print();
    	}
    }

     

    javac Main.java를 통해 Main.java를 컴파일시

    cp옵션 sourcepath옵션 미정의로 Main.java컴파일에 관련된 클래스 파일들,소스 파일들을 현재 디렉토리 하위에서 찾는다. 이때 root디렉토리 내부에 관련된 파일들이 모두 존재하지만 컴파일이 되지 않는 이유는 관련된 파일들이 패키지에 맞는 디렉토리 구조로 이루어지지 않았기 때문이다.

     

    자바에서는 다른 패키지에 동일한 이름의 클래스가 여러개 존재할 수 있고, 여러 문제로 인해 특정한 약속이 필요하다.

    컴파일러가 관련된 파일들을 찾을 때는 명시된 경로들을 모두 루트로 잡아 패키지에 매칭된 디렉토리에서 관련된 클래스파일 또는 자바 파일을 찾게된다.

     

    javac Main.java의 문제를 풀어보면 Main.java내부의 import a.A를 통해 root디렉토리 하위에 a디렉토리에서 A와 관련된 파일들을 찾게된다.

     

    root에 a디렉토리를 만들고 이전에 컴파일했던 A.class파일을 넣고 root에서 javac Main.java를 입력하면

    root에 존재하는 A.class파일과 A.java소스파일은 패키지에 맞지 않아 컴파일러에 의해 참조되지 않아 문제가 되지 않는다.

     

    Main.class의 main함수 호출 결과

    java명령어에도 cp옵션이 존재하는데 미정의시 명령어를 입력한 현재 디렉토리이므로 root/a에서 A.class를 찾는다.


    소스 파일을 하나씩 컴파일해봤지만 다수의 소스 파일을 한번에 컴파일 하려면 참조될 소스 파일들을 패키지에 맞춘 디렉토리 구조로 위치 시키면된다.

    root 디렉토리에서 Main.java를 컴파일하면 옵션들 미정의로 root하위에서 관련된 파일들을 패키지에 대응되는 디렉토리 에서 class파일을 찾거나 class파일이 없으면 소스파일을 찾아 추가적으로 컴파일하여 Main.class를 생성한다.

    -d 옵션 미정의로 인해 소스 파일이 존재하는 곳에 생성된 클래스 파일들이 배치된다.

     

    생성된 클래스 파일들을 모두 지우고 -d 옵션을 사용하여 클래스 파일을 따로 뽑아보면

    생성된 클래스 파일들을 현재 디렉토리 . 하위의 target디렉토리에 저장

    target에서 java Main을 입력하면 된다.


    classpath옵션과 sourcepath옵션 경로가 다를시

     

    A.java

    package a;
    
    public class A{
    	public static void print(){
    		System.out.println("A");
    	}
    }

     

    B.java

    package b;
    
    public class B{
    	public static void print(){
    		System.out.println("B");
    	}
    }

     

    Main.java

    import a.A;
    import b.B;
    
    public class Main{
    	public static void main(String[] args){
    		new A().print();
    		new B().print();
    	}
    }

     

    root/testclasspath에 class 파일들만 배치

     

    root/testsourcepath에 소스 파일들만 배치

    testclasspath에 참조될 클래스 파일들이 모두 존재하기 때문에 testsourcepath하위의 소스파일들은 Main.java컴파일 과정에서 추가적으로 컴파일되지 않는다.

    댓글

Designed by Tistory.