경주장

7주차 과제: 패키지 #7 클래스패스 (~02.30) 본문

JAVA/whiteship_live-study

7주차 과제: 패키지 #7 클래스패스 (~02.30)

달리는치타 2022. 2. 25. 14:14

✔️ 학습할 것 (필수)

+ 패키지란?

  • package 키워드
  • import 키워드
  • 클래스패스
  • CLASSPATH 환경변수
  • -classpath 옵션
  • 접근지시자

클래스패스란?

Def) Classpath
ClassPath ​is a parameter in JVM or the Java compiler that specifies the location of user-defined classes and packages. The parameter may be set either on the command-line,or through an enviroment variable

 

전통적인 Dynamic Loading의 특성과 유사하게, 자바 프로그램을 실행할때 JVM은 classes를 Lazy하게 find/load합니다. 즉, 클래스의 바이트코드를 클래스가 처음 사용될 때 load합니다. 이때 classpath 는 java에게 classes (바이트코드 바일)을 찾아야할 file system 상의 경로를 알려줍니다.

JVM은 아래와 같은 순서로 .class 파일을 찾고 로드합니다.

  1. bootstrap 클래스 - java.lang과 같은 모든 자바 코어 라이브러리의 클래스
  2. extention 클래스
    • jar 파일에 정의 된 클래스
      packages that are in the extension directory of the JRE or JDK, jre/lib/ext/ -
  3. user-defined packages and libraries

@See Also) - 클래스 로더

 

1주차 과제: JVM은 무엇이며 자바 코드는 어떻게 실행하는 것인가.

매주 일요일 목요일...을 마감으로 생각해서 백기선님의 온라인 자바 스터디를 진행하겠습니다. GitHub - whiteship/live-study: 온라인 스터디 온라인 스터디. Contribute to whiteship/live-study development b..

running-cheetah.tistory.com

저희는 평소에 IDE의 도움으로 클래스패스와 패키지의 경로에 대한 고민을 하지 않고 편하게 개발에 집중할 수 있습니다. 하지만 항상 이러한 도움을 받을 수 있는 것이 아니니 직접 자바 파일을 컴파일 하고 실행/배포 하는 법을 알아둔다면 장기적으로 큰 도움이 될 것입니다.


클래스 패스를 명시적으로 적용하는 예제를 살펴 보겠습니다.

세 개의 클래스를 가진 하나의 HelloWorld.java 파일을 컴파일 하면 세 개의 클래스 파일 (바이트 코드)이 생성됩니다.

 

컴파일 후 생성된 세 개의 클래스 파일

 

.class 파일을 JVM에 올리고 실행하기 위해서는 java 명령어를 활용해야 합니다.

이때 Helloworld 클래스를 패키지를 고려하여 classpath를 지정해야합니다. 

 

package week7_package.study.classpath;

JVM입장에서는 Classpath를 기준으로 위 패키지를 지닌 class 파일이 

classpath:/week7_package/study/classpath 의 경로에 있기를 기대합니다.

 

따라서 classpath는 절대경로로 C:\Users\1\Desktop\java\live-study-assignment\live-study\src\main\java 로 정해져야합니다.

 

-classpath 옵션을 통해 클래스 패스를 지정하고 java 명령어로 자바 프로그램을 실행 할 수 있습니다.

 

이때 classes파일의 경로를 외부로 빼 봅시다!

mytarget/week7_package/study/classpath

바이트 코드를 외부로 빼고 같은 명령어를 실행하면

메인 클래스를 찾을 수 없고 그 이름은 week7_package.study.classpath.HelloWorld임을 알려줍니다. - ClassNotFoundException

 

src\main\java아래 패키지 경로인 week7_package\study\classpath\아래 .class 파일들이 없기 때문에

src\main\java는 더이상 클래스 패스로서 기능 하지 못합니다.

 

대신에 새롭게 이사한 클래스패스인 mytarget을 경로로 클래스 패스의 옵션에 넣어주면 정상적으로 클래스를 찾습니다.

짠!

이쯤에서 정리하는 classpath의 역할은 아래와 같습니다.

  • JAR 파일 및
  • 패키지 계층 구조의 최상위 경로의 집합입니다.

위의 예제을 통해 classpath가 패키지 계층 구조의 최상단임을 확인하였습니다.


이번에는 "집합"이라는 단어에 집중해 보겠습니다.

mytarget아래 3개의 클래스파일 중 SupportClass.class 파일을 잠깐 삭제하면 아래와 같은 에러가 발생합니다.

ClassNotFoundException -> NoClassDefFoundError

 

이제 SupportClass.class를 다른 classpath에 저장하고 두개의 클래스패스를 조합하여 자바 명령어로 실행해보겠습니다.

분리된 .class 파일들
짠!

semi colon으로 여러개의 클래스패스를 옵션으로 전달 할 수 있습니다.


.jar 파일 에의해 로딩되는 extention 클래스들을 classpath에 전달하는 명령어를 살펴보겠습니다. 이번에는 인텔리제이 IDE의 도움을 받겠습니다.

 

간단하게 인텔리제이의 Run을 통해 HelloWolrd.main을 실행 하면 아래와 같은 명령어를 활용함을 알 수 있습니다.

//명령어 입니다.
"C:\Program Files\Java\jdk-11.0.12\bin\java.exe" 
"-javaagent:
C:\Program Files\JetBrains\IntelliJ IDEA 2021.2.1\lib\idea_rt.jar=4189:
C:\Program Files\JetBrains\IntelliJ IDEA 2021.2.1\bin" 

-Dfile.encoding=UTF-8 
-classpath 
C:\Users\1\Desktop\java-study\live-study-assignment\live-study\target\classes;
C:\Users\1\.m2\repository\org\kohsuke\github-api\1.301\github-api-1.301.jar;
C:\Users\1\.m2\repository\org\apache\commons\commons-lang3\3.9\commons-lang3-3.9.jar;
C:\Users\1\.m2\repository\com\fasterxml\jackson\core\jackson-databind\2.13.0\jackson-databind-2.13.0.jar;
C:\Users\1\.m2\repository\com\fasterxml\jackson\core\jackson-annotations\2.13.0\jackson-annotations-2.13.0.jar;
C:\Users\1\.m2\repository\com\fasterxml\jackson\core\jackson-core\2.13.0\jackson-core-2.13.0.jar;
C:\Users\1\.m2\repository\commons-io\commons-io\2.8.0\commons-io-2.8.0.jar 

week7_package.study.classpath.HelloWorld

//실행결과 입니다.
HelloWorld.main

-classpath외 에도 -javaagent, -Dfile.encoding의 옵션을 자동으로 포함합니다.

classpath 부분을 살펴 보면 처음에는 user-defined package and libraries에 해당되는 클래스 파일을 모아놓는 경로인 target\classes가 있고 이후에는 여러 jar 파일들이 자동으로 추가되어 있음을 확인 할 수 있습니다.

 

이는 지난 과제를 수행하면서 pom.xml에 추가한 github-api에 대한 의존성 때문에 추가된 것입니다.

<dependency>
    <groupId>org.kohsuke</groupId>
    <artifactId>github-api</artifactId>
    <version>1.301</version>
</dependency>

깃헙 API는 내부적으로 위의 jar 파일에 해당하는 dependency를 모두 가지고 있으며 Maven 빌드를 통해 jar파일의 형태로 pc에 다운로드 되어 Run할때는 자동으로 classpath로 추가됩니다.

github-api의 의존성


다시한번 클래스 패스의 역할을 살펴보면 아래와 같습니다.

클래스 패스는 

  • JAR 파일 및
  • 패키지 계층 구조의 최상위 경로의 집합입니다.

classpath는 옵션으로 전달하는 방법 외에도 환경 변수로 설정할 수 있습니다.

이부분에 대한 실습은 생략하겠습니다. 

제 PC에는 현재 위와 같이 설정되어 있습니다. 혹시 저부분이 bootstrap class에 대한 classpath를 담당하는 것인지 확인해보기 위해 저 환경변수를 삭제하고 main함수의 인자인 String에 대한 ClassNotFoundException이 발생하기를 기대하며  HelloWorld.main을 실행해보았지만 정상적으로 출력되었습니다. 아마 jvm내부적으로 이미 bootstrap class에대한 classpath를 가지고 있는 것으로 추측됩니다. 혹시 잘 아시는 분은 댓글 부탁드립니다.

 


접근 제어자에 대한 학습은 5주차 클래스에서 학습한 내용으로 대체하겠습니다.

@See Also)

 

5주차 과제: 클래스 #5 (~02.15)

학습할 것 (필수) 클래스 정의하는 방법 객체 만드는 방법 (new 키워드 이해하기) 메소드 정의하는 방법 생성자 정의하는 방법 this 키워드 이해하기 졸업과 이사, Programmers Backend 스터디 프로그램

running-cheetah.tistory.com

 

@출처)

 

Setting the Class Path

Class Path Wild Cards Class path entries can contain the base name wildcard character (*), which is considered equivalent to specifying a list of all of the files in the directory with the extension .jar or .JAR. For example, the class path entry mydir/* s

docs.oracle.com

 

 

Classpath - Wikipedia

Classpath is a parameter in the Java Virtual Machine or the Java compiler that specifies the location of user-defined classes and packages. The parameter may be set either on the command-line, or through an environment variable. Overview and architecture[e

en.wikipedia.org