참고:
- 이 자습서는 Oracle에서 제공하는 무료 실습 환경에서 사용할 수 있습니다.
- Oracle Cloud Infrastructure 인증서, 테넌시 및 구획에 대한 예제 값이 사용됩니다. 랩을 완료한 후에는 이러한 값을 클라우드 환경과 관련된 값으로 대체하십시오.
GraalVM Native Image 시작하기
소개
이 실습에서는 GraalVM Native Image를 사용하여 클라우드 전용 Java 애플리케이션을 구축하는 프로세스를 단계별로 안내합니다. 본 과정은 Java에 대한 지식을 갖춘 개발자를 대상으로 합니다.
GraalVM Native Image 기술은 Java 코드를 사전에 포함된 실행 파일로 컴파일합니다. 응용 프로그램에서 런타임 시 필요한 코드만 실행 파일에 추가됩니다.
Native Image로 생성된 실행 파일에는 다음과 같은 여러 가지 중요한 이점이 있습니다.
- JVM에서 필요한 리소스의 일부분을 사용하므로 실행하는 것이 더 저렴합니다.
- 밀리초 단위로 시작
- 걱정 없이 즉시 최대의 성능 제공
- 더 빠르고 효율적인 배포를 위해 경량 컨테이너 이미지에 패키지화할 수 있습니다.
- 공격 영역 감소(이후 랩에서 더 많이)
오늘날 많은 마이크로서비스 프레임워크에서 Micronaut, Spring, Helidon, Quarkus 등 GraalVM Native Image를 사용한 사전 컴파일을 지원합니다.
또한 Native Image용 Maven 및 Gradle 플러그인이 있으므로 Java 애플리케이션을 실행 파일로 쉽게 빌드, 테스트 및 실행할 수 있습니다.
주: OCI(Oracle Cloud Infrastructure)는 추가 비용 없이 GraalVM Enterprise를 제공합니다.
예상 랩 시간: 45분
랩 목표
이 연습에서는 다음 작업을 수행합니다.
- Oracle Cloud의 원격 호스트에 접속합니다. Oracle Cloud 컴퓨트 호스트에서 애플리케이션을 개발할 것입니다.
- GraalVM을 사용하여 Java 애플리케이션 빌드 및 실행
- GraalVM Native Image를 사용하여 Java 애플리케이션을 실행 파일로 변환
- Java의 동적 기능과 함께 작동하는 실행 파일 작성
- Maven GraalVM 플러그인을 사용하여 GraalVM Native Image로 실행 파일 작성
참고: 랩탑 아이콘이 나타나면 명령을 입력하는 것과 같은 작업을 수행해야 합니다. 이를 위해 시선을 집중하십시오.
# This is where we you will need to do something
STEP 1: 원격 호스트에 연결하고 개발 환경을 확인합니다.
개발 환경은 원격 호스트(Oracle Linux 8, 1 CPU 및 32GB 메모리 포함)에 의해 제공됩니다.
원격 호스트가 준비되기 전에 Luna Labs 데스크탑 환경이 표시되므로 최대 2분이 걸릴 수 있습니다.
Luna Desktop 환경에서 설치 스크립트를 실행하여 원격 호스트에 연결합니다. 이 스크립트는 리소스 탭을 통해 사용할 수 있습니다.
-
바탕 화면에서 Luna-Lab.html 아이콘을 두 번 누릅니다. 그러면 Oracle Cloud Infrastructure 자격 증명과 실습 관련 정보가 표시됩니다.
-
리소스 탭이 표시됩니다. 컴퓨트 인스턴스가 teh 클라우드에서 프로비저닝되는 동안 리소스 제목 옆에 표시된 안개가 회전합니다.
-
인스턴스가 프로비전되면 최대 2분 정도 걸릴 수 있으며 이때 리소스 탭에 다음과 같은 메시지가 표시됩니다.
-
리소스 탭에서 VS 코드 환경을 설정하는 구성 스크립트를 복사합니다. 세부정보 보기 링크를 눌러 구성을 표시합니다. 아래 스크린샷에 표시된 대로 복사합니다.
-
아래 스크린샷에 표시된 대로 터미널을 엽니다.
-
구성 코드를 터미널에 붙여넣어 VS 코드를 엽니다.
모든 것입니다. 축하합니다. 이제 Oracle Cloud의 원격 호스트에 성공적으로 접속되었습니다!
개발 환경에 대한 참고 사항
이 실습을 위한 Java 플랫폼으로 GraalVM Enterprise 21을 사용합니다. GraalVM은 신뢰할 수 있는 보안 Oracle Java SE에 구축된 Oracle의 고성능 JDK 배포입니다.
개발 환경은 이 실습에 필요한 GraalVM 및 Native Image 툴로 사전 구성되어 있습니다.
터미널에서 이러한 명령을 실행하여 쉽게 확인할 수 있습니다. VS 코드 Terminal > New Terminal
내에서 터미널을 만들 수 있습니다.
java -version
native-image --version
STEP 2: 데모 응용 프로그램 빌드 및 실행
데모 응용 프로그램을 사용하여 GraalVM Native Image: 현재 디렉토리와 해당 하위 디렉토리의 파일 수를 계산하는 명령행 Java 응용 프로그램을 보여줍니다. 또한 응용 프로그램은 총 파일 크기도 계산합니다.
응용 프로그램의 소스 코드는 원격 호스트에서 사용할 수 있습니다.
데모 애플리케이션에 대한 참고 사항
응용 프로그램은 src
디렉토리에서 찾을 수 있는 두 개의 Java 파일로 구성됩니다.
App.java
:ListDir
클래스의 래퍼입니다.ListDir.java
: 모든 작업을 수행합니다. 파일 수를 계산하고 출력을 요약합니다.
수동으로 또는 Maven 프로파일을 사용하여 응용 프로그램을 빌드할 수 있습니다. Maven 빌드 구성은 pom.xml
파일에서 제공됩니다. Maven 프로파일은 단일 pom.xml
파일 내에서 다른 빌드 구성을 사용하는 좋은 방법입니다. Maven 프로파일에 대한 자세한 내용은 여기서 찾아볼 수 있습니다.
열린 VS 코드 내에서 파일을 찾아볼 수 있습니다.
이 실습에서는 각각 특정 목적을 가진 여러 프로파일이 사용됩니다.
native
: 이 프로파일은 GraalVM Native Image를 사용하여 실행 파일을 작성합니다.java_agent
: 이 프로파일은 응용 프로그램에서 모든 동적 코드 사용을 추적하고 이 정보를 구성 파일로 캡처하는 추적 에이전트를 사용하여 Java 응용 프로그램을 작성합니다. 나중에 자세히 알아보겠습니다.
특정 Maven 프로파일을 mvn
명령에 매개변수로 전달하여 사용합니다. 프로파일 이름은 -P
플래그에 추가됩니다. VS 코드 내에서 터미널 내에서 다음 명령을 실행할 수 있습니다.
아래 예제는 Maven을 사용하여 구축할 때 native
프로파일을 호출할 수 있는 방법을 보여줍니다.
mvn clean package -Pnative
이제 응용 프로그램이 실행되는 작업을 기본적으로 이해하여 작동 방식을 확인할 수 있습니다.
-
VS Code에서 연 터미널 내에서 프로젝트를 빌드하고 실행합니다.
mvn clean package exec:exec
위 명령은 다음을 수행합니다.
- 프로젝트를 정리하여 생성되거나 컴파일된 아티팩트를 제거합니다.
- 응용 프로그램을 포함하는 실행 가능한 JAR 파일을 생성합니다. 이 JAR 파일은 나중에 Native Image에서 사용됩니다.
exec
플러그인을 실행하여 응용 프로그램을 실행합니다.
생성된 출력에 다음이 포함됩니다(응용 프로그램에서 보고된 파일 수는 다를 수 있음).
Counting directory: . Total: 15 files, total size = 511.9 KiB [INFO] ------------------------------------------------------------------------ [INFO] BUILD SUCCESS [INFO] ------------------------------------------------------------------------
STEP 3: Java 응용 프로그램을 실행 파일로 설정합니다.
이제 GraalVM Native Image를 사용하여 응용 프로그램의 실행 버전을 작성합니다. 빠른 미리 알려 드리면 GraalVM Native Image는 Java 애플리케이션을 JDK를 실행할 필요가 없는 자체 포함된 실행 파일로 변환하는 사전 컴파일 기술로서, 빠르고 효율적입니다.
GraalVM Native Image는 원격 호스트에 사전 설치되어 있습니다.
-
시작하려면
target
디렉토리에 컴파일된 JAR 파일이 있는지 확인합니다.ls ./target drwxrwxr-x 1 krf krf 4096 Mar 4 11:12 archive-tmp drwxrwxr-x 1 krf krf 4096 Mar 4 11:12 classes drwxrwxr-x 1 krf krf 4096 Mar 4 11:12 generated-sources -rw-rw-r-- 1 krf krf 496273 Mar 4 11:38 graalvmnidemos-1.0-SNAPSHOT-jar-with-dependencies.jar -rw-rw-r-- 1 krf krf 7894 Mar 4 11:38 graalvmnidemos-1.0-SNAPSHOT.jar drwxrwxr-x 1 krf krf 4096 Mar 4 11:12 maven-archiver drwxrwxr-x 1 krf krf 4096 Mar 4 11:12 maven-status
필요한 파일은
graalvmnidemos-1.0-SNAPSHOT-jar-with-dependencies.jar
입니다. -
명령행에서 실행 파일을 생성합니다. GraalVM Native Image를 사용하기 위해 Maven 플러그인을 사용할 필요는 없지만 도움을 줄 수 있습니다. 프로젝트의 루트 디렉토리
demo
에서 다음을 실행합니다.native-image -jar ./target/graalvmnidemos-1.0-SNAPSHOT-jar-with-dependencies.jar --no-fallback -H:Class=oracle.App -H:Name=file-count
그러면 현재 디렉토리 내에
file-count
라는 실행 파일이 생성됩니다. -
다음과 같이 이 실행 파일을 실행합니다.
./file-count
-
이제 응용 프로그램을 시작합니다. 먼저 실행 파일로 실행한 다음 일반
java
명령을 사용하여 실행합니다.time ./file-count
time java -cp ./target/graalvmnidemos-1.0-SNAPSHOT-jar-with-dependencies.jar oracle.App
native-image
명령으로 생성된 실행 파일은 해당하는 Java 응용 프로그램보다 훨씬 빠르게 실행됩니다.
실행 파일 작성 방법에 대해 좀 더 자세히 살펴보겠습니다.
2단계에서 native-image
명령으로 전달한 매개변수는 어떻게 지정합니까?
-jar
: Java 응용 프로그램을 포함하는 JAR 파일의 위치를 지정합니다.-cp
를 사용하여 클래스 경로를 지정할 수도 있습니다.--no-fallback
: 폴백 이미지를 생성하지 않습니다. 폴백 이미지를 실행하려면 JVM이 필요하며, 필요하지 않습니다.-H:Class
: 시작점 메소드(main
메소드)를 제공하는 클래스를 지정합니다.-H:Name
: 출력 실행 파일의 이름을 지정합니다.
전체 설명서는 여기에서 확인할 수 있습니다.
GraalVM Native Image Maven 플러그인을 사용하여 native-image
툴을 실행할 수도 있습니다. 프로젝트 pom.xml
(Maven 구성) 파일에는 플러그인을 사용하여 실행 파일을 작성하는 방법을 보여주는 다음 코드 조각이 포함되어 있습니다.
<!-- Native Image -->
<plugin>
<groupId>org.graalvm.buildtools</groupId>
<artifactId>native-maven-plugin</artifactId>
<version>${native.maven.plugin.version}</version>
<extensions>true</extensions>
<executions>
<execution>
<id>build-native</id>
<goals>
<goal>build</goal>
</goals>
<phase>package</phase>
</execution>
</executions>
<configuration>
<skip>false</skip>
<imageName>${exe.file.name}</imageName>
<mainClass>${app.main.class}</mainClass>
<buildArgs>
<buildArg>--no-fallback</buildArg>
<buildArg>--report-unsupported-elements-at-runtime</buildArg>
</buildArgs>
</configuration>
</plugin>
Native Image Maven 플러그인은 실행 파일을 많이 생성하는 작업을 수행합니다. <skip>true</skip>
태그를 사용하여 사용 안함으로 설정할 수 있습니다. <buildArgs/>
태그를 통해 native-image
에 매개변수를 전달할 수도 있습니다.
GraalVM Native Image 플러그인에 대한 전체 설명서는 여기에서 찾을 수 있습니다.
Maven 프로파일을 사용하여 실행 파일을 작성하려면 다음을 실행합니다.
mvn clean package -Pnative
Maven 빌드는 실행 파일 file-count
을 target
디렉토리에 배치합니다.
다음과 같이 실행 파일을 실행할 수 있습니다.
./target/file-count
STEP 4: 반사 사용 - Log4J에 종속성 추가
이 단계에서는 Java의 동적 기능과 함께 작동하는 실행 파일을 작성합니다.
리플렉션에 의존하는 응용 프로그램에 라이브러리 또는 일부 코드를 추가하려고 한다고 가정합니다. 리플렉션 테스트에 적합한 후보는 Log4J 로깅 프레임워크입니다. 프로젝트 pom.xml
파일에 이미 종속성으로 추가되었습니다.
<dependency>
<groupId>log4j</groupId>
<artifactId>log4j</artifactId>
<version>1.2.17</version>
</dependency>
log4j
를 사용하도록 응용 프로그램을 변경하려면 ListDir.java
파일을 편집하고 몇 줄의 주석 처리를 해제합니다.
-
VS 코드를 사용하여
ListDir.java
파일을 엽니다. -
log4j
임포트를 선언하는 행의 주석 처리를 해제한 다음 다음 다음 행의 주석 처리를 해제합니다.//import org.apache.log4j.Logger;
//final static Logger logger = Logger.getLogger(ListDir.class);
/* // Add some logging if(logger.isDebugEnabled()){ logger.debug("Processing : " + dirName); } */
/* // Add some logging if(logger.isDebugEnabled()){ logger.debug("Processing : " + f.getAbsolutePath()); } */
-
파일을 저장합니다
이제 응용 프로그램에 로깅을 추가했으므로 재구축 및 실행하여 변경 결과를 볼 수 있습니다.
mvn clean package exec:exec
앞에서 살펴본 것과 같은 종류의 출력이 나타나지만 로깅을 더 추가하면 됩니다.
-
그런 다음 Maven 프로파일을 사용하여 실행 파일을 작성합니다.
mvn clean package -Pnative
-
로깅이 포함된 실행 파일을 실행합니다.
./target/file-count
오류가 발생합니다.
Exception in thread "main" java.lang.NoClassDefFoundError at org.apache.log4j.Category.class$(Category.java:118) at org.apache.log4j.Category.<clinit>(Category.java:118) at java.lang.Class.ensureInitialized(DynamicHub.java:552) at oracle.ListDir.<clinit>(ListDir.java:75) at oracle.App.main(App.java:63) Caused by: java.lang.ClassNotFoundException: org.apache.log4j.Category at java.lang.Class.forName(DynamicHub.java:1433) at java.lang.Class.forName(DynamicHub.java:1408) ... 5 more
여기서 무슨 일이 일어난 거지?
Java의 동적 기능 사용
이 예외는 반사에 의존하므로 Log4J 라이브러리를 추가함으로써 발생합니다.native-image
도구는 공격적인 정적 분석을 수행하여 응용 프로그램 내에서 사용되는 클래스를 확인합니다. 사용되지 않는 클래스에 대해서는 해당 클래스가 필요하지 않다고 가정합니다. 이를 "열린 세계" 가정이라고 합니다. 로드해야 하는 모든 사항은 실행 파일을 작성할 때 알려져야 합니다. 정적 분석으로 찾을 수 없는 경우 실행 파일에 포함되지 않습니다.
Reflection은 Java의 핵심 기능이므로 리플렉션을 사용하고 GraalVM Native Image에서 제공하는 빠른 속도를 활용하는 방법은 무엇입니까? native-image
도구에서 반사 사용에 대해 알아볼 수 있는 방법이 필요합니다.
다행히 native-image
도구는 고찰을 통해 참조되는 모든 클래스를 지정하는 구성 파일에서 읽을 수 있습니다.
이 작업은 수동으로 수행하거나 GraalVM Java 런타임과 함께 제공되는 Java 추적 에이전트를 통해 수행할 수 있습니다. 에이전트는 응용 프로그램이 실행되는 동안 찾을 수 있는 반사, JNI, 프록시 및 리소스 액세스의 모든 인스턴스를 기록하는 JSON 파일을 생성합니다.
주: 모든 고찰 사례가 식별되도록 추적 에이전트를 실행할 때 응용 프로그램의 모든 코드 경로를 수행하는 것이 중요합니다.
추적 에이전트에 대한 전체 설명서는 여기에서 확인할 수 있습니다.
STEP 5: 추적 에이전트 사용
이제 응용 프로그램을 실행하는 동안 추적 에이전트를 사용하여 반사 구성을 생성합니다.
-
추적 에이전트를 사용하여 응용 프로그램을 실행합니다.
java -agentlib:native-image-agent=config-output-dir=./src/main/resources/META-INF/native-image -cp ./target/graalvmnidemos-1.0-SNAPSHOT-jar-with-dependencies.jar oracle.App
추적 에이전트가 생성한 구성 파일을 확인합니다.
ls -l src/main/resources/META-INF/native-image/
생성된 출력에 다음이 포함됩니다.
total 56 -rw-r--r-- 1 kfoster staff 4B Dec 2 19:13 jni-config.json -rw-r--r-- 1 kfoster staff 86B Nov 9 20:46 native-image.properties -rw-r--r-- 1 kfoster staff 65B Dec 2 19:13 predefined-classes-config.json -rw-r--r-- 1 kfoster staff 4B Dec 2 19:13 proxy-config.json -rw-r--r-- 1 kfoster staff 521B Dec 2 19:13 reflect-config.json -rw-r--r-- 1 kfoster staff 101B Dec 2 19:13 resource-config.json -rw-r--r-- 1 kfoster staff 4B Dec 2 19:13 serialization-config.json
주: 프로젝트에 이 작업을 수행할 수 있는 Maven 프로파일이 포함되어 있습니다. 다음 명령을 실행하여 추적 에이전트를 사용합니다.
mvn clean package exec:exec -Pjava_agent
-
이제 실행 파일을 다시 빌드합니다. 이번에는 추적 에이전트로 생성된 구성 파일이 적용됩니다.
mvn package -Pnative
-
마지막으로 생성된 파일을 실행합니다.
time ./target/file-count
실행 파일이 작동하고 예상대로 출력에 로그 메시지를 생성합니다.
이는 추적 에이전트가 생성한 파일이 반사에서 참조하는 클래스를 기록했기 때문입니다. 이제 native-image
도구는 응용 프로그램 내에서 사용되고 있으므로 생성된 실행 파일에서 제외하지 않습니다.
-agentlib
매개변수의 위치에 대한 참고
에이전트 매개변수는 반드시 -jar
또는 -classpath
매개변수 앞에 와야 합니다. 또한 파일을 쓸 디렉토리도 지정해야 합니다. 권장 위치는 src/main/resources/META-INF/native-image
아래에 있습니다. 이 위치에 배치된 파일은 native-image
도구에서 자동으로 선택됩니다.
실행 파일 생성 구성에 대한 참고 사항
Java 속성 파일(기본적으로 src/main/resources/META-INF/native-image/native-image.properties
)을 사용하여 native-image
도구로 매개변수를 전달할 수도 있습니다. demo
디렉토리에 가능한 작업을 알려주는 예제 파일이 있습니다.
결론
이 실습에서는 여러 가지 GraalVM Native Image 기능을 사용해 보았습니다.
- Java 명령행 응용 프로그램에서 빠른 실행 파일을 생성하는 방법
- Maven을 사용하여 실행 파일을 작성하는 방법
- 추적 에이전트를 사용하여 반사 추적 및 기록 프로세스를 자동화하는 방법
GraalVM Native Image를 사용하여 효율적이고 안전하며 즉시 확장 가능한 클라우드 네이티브 Java 애플리케이션 작성
더 알아보기
- Native Image Architect Christian Wimmer GraalVM Native Image: Large Static Analysis for Java의 프레젠테이션 보기
- GraalVM Native Image Reference 설명서
추가 학습 자원
docs.oracle.com/learn에서 다른 실습을 찾아보거나 Oracle Learning YouTube channel에서 무료 학습 콘텐츠에 액세스할 수 있습니다. 또한 education.oracle.com/learning-explorer를 방문하여 Oracle Learning Explorer로 변경하십시오.
제품 설명서는 Oracle Help Center를 참조하십시오.
GraalVM Native Image Quick Start
F51530-04
March 2022
Copyright © 2022, Oracle and/or its affiliates.