Skip to content

Commit 136260a

Browse files
committed
feat: 순수 Java 파일을 NativeImage로 변환하는 예제
1 parent 2d5d2bb commit 136260a

File tree

6 files changed

+315
-2
lines changed

6 files changed

+315
-2
lines changed

graalvm-example/README.md

Lines changed: 170 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,173 @@
1-
# Getting Started
1+
# 그랄VM 예제
2+
- 언어: Java 22
3+
- 프레임워크: SpringBoot 3.2
4+
- Apple Silicon M2 Pro
5+
- 운영체제: MacOS 14.0(Sonoma 23A344)
26

3-
![img.png](img.png)
47

8+
# GraalVM은 어떻게 동작하는가?
9+
10+
nothing.
11+
12+
13+
14+
15+
<!-- ###################################################################################################################################### -->
16+
<!-- ###################################################################################################################################### -->
17+
<!-- ###################################################################################################################################### -->
18+
<br/>
19+
20+
# Example (순수 자바)
21+
22+
### GraalVM 설치하기
23+
설치하기
24+
https://www.graalvm.org/downloads/
25+
26+
### 예제 코드 작성
27+
![img_1.png](img_1.png)
28+
29+
```java
30+
// package graalvm.graalvmexample; // <- 이것을 작성하지 않도록 주의!
31+
32+
public class HelloWorld {
33+
public static void main(String[] args) {
34+
System.out.println("HEllo World");
35+
}
36+
}
37+
```
38+
39+
### 바이트코드로 컴파일하기
40+
`javac` 명령을 통해 바이트코드로 컴파일한다.
41+
```shell
42+
   ~/Doc/GitHub/SpringExample/graalvm-example/src/main/java/graalvm/graalvmexample    GraalVM +11 !4 ?43  javac HelloWorld.java  ✔  14:28:04 
43+
```
44+
45+
### NativeImage로 만들기
46+
`native-image` 명령을 통해 플랫폼에 맞는 기계어로 변환한다.
47+
```shell
48+
   ~/Doc/GitHub/SpringExample/graalvm-example/src/main/java/graalvm/graalvmexample    GraalVM +11 !4 ?44  native-image HelloWorld  ✔  14:32:50 
49+
========================================================================================================================
50+
GraalVM Native Image: Generating 'helloworld' (executable)...
51+
========================================================================================================================
52+
[1/8] Initializing... (11.4s @ 0.10GB)
53+
Java version: 22.0.2+9, vendor version: Oracle GraalVM 22.0.2+9.1
54+
Graal compiler: optimization level: 2, target machine: armv8-a, PGO: off
55+
C compiler: cc (apple, arm64, 15.0.0)
56+
Garbage collector: Serial GC (max heap size: 80% of RAM)
57+
1 user-specific feature(s):
58+
- com.oracle.svm.thirdparty.gson.GsonFeature
59+
------------------------------------------------------------------------------------------------------------------------
60+
Build resources:
61+
- 12.09GB of memory (75.6% of 16.00GB system memory, determined at start)
62+
- 12 thread(s) (100.0% of 12 available processor(s), determined at start)
63+
[2/8] Performing analysis... [****] (3.7s @ 0.19GB)
64+
2,056 reachable types (59.9% of 3,430 total)
65+
1,849 reachable fields (38.8% of 4,760 total)
66+
8,637 reachable methods (35.5% of 24,345 total)
67+
778 types, 25 fields, and 348 methods registered for reflection
68+
49 types, 33 fields, and 48 methods registered for JNI access
69+
4 native libraries: -framework Foundation, dl, pthread, z
70+
[3/8] Building universe... (0.6s @ 0.21GB)
71+
[4/8] Parsing methods... [*] (0.4s @ 0.22GB)
72+
[5/8] Inlining methods... [***] (0.4s @ 0.26GB)
73+
[6/8] Compiling methods... [***] (6.9s @ 0.33GB)
74+
[7/8] Laying out methods... [*] (0.5s @ 0.34GB)
75+
[8/8] Creating image... [*] (0.9s @ 0.37GB)
76+
2.62MB (44.08%) for code area: 3,897 compilation units
77+
3.13MB (52.49%) for image heap: 51,987 objects and 71 resources
78+
209.35kB ( 3.43%) for other data
79+
5.95MB in total
80+
------------------------------------------------------------------------------------------------------------------------
81+
Top 10 origins of code area: Top 10 object types in image heap:
82+
1.26MB java.base 695.51kB byte[] for java.lang.String
83+
1.14MB svm.jar (Native Image) 692.82kB byte[] for code metadata
84+
80.79kB com.oracle.svm.svm_enterprise 364.24kB java.lang.String
85+
25.46kB org.graalvm.nativeimage.base 332.24kB java.lang.Class
86+
22.27kB jdk.proxy3 143.75kB java.util.HashMap$Node
87+
21.27kB org.graalvm.collections 122.16kB heap alignment
88+
19.61kB jdk.proxy1 114.52kB char[]
89+
14.85kB jdk.graal.compiler 86.09kB java.lang.Object[]
90+
14.50kB jdk.internal.vm.ci 80.48kB byte[] for reflection metadata
91+
8.26kB jdk.proxy2 80.31kB com.oracle.svm.core.hub.DynamicHubCompanion
92+
456.00B for 1 more packages 487.87kB for 532 more object types
93+
Use '-H:+BuildReport' to create a report with more details.
94+
------------------------------------------------------------------------------------------------------------------------
95+
Security report:
96+
- Binary includes Java deserialization.
97+
- Use '--enable-sbom' to embed a Software Bill of Materials (SBOM) in the binary.
98+
------------------------------------------------------------------------------------------------------------------------
99+
Recommendations:
100+
PGO: Use Profile-Guided Optimizations ('--pgo') for improved throughput.
101+
HEAP: Set max heap for improved and more predictable memory usage.
102+
CPU: Enable more CPU features with '-march=native' for improved performance.
103+
QBM: Use the quick build mode ('-Ob') to speed up builds during development.
104+
------------------------------------------------------------------------------------------------------------------------
105+
1.0s (3.9% of total time) in 408 GCs | Peak RSS: 0.69GB | CPU load: 4.23
106+
------------------------------------------------------------------------------------------------------------------------
107+
Build artifacts:
108+
/Users/hyeon/Documents/GitHub/SpringExample/graalvm-example/src/main/java/graalvm/graalvmexample/helloworld (executable)
109+
========================================================================================================================
110+
Finished generating 'helloworld' in 25.3s.
111+
```
112+
113+
### 실행하기
114+
생성된 helloworld를 실행할 수 있다.
115+
116+
![img_2.png](img_2.png)
117+
118+
119+
120+
<!-- ###################################################################################################################################### -->
121+
<!-- ###################################################################################################################################### -->
122+
<!-- ###################################################################################################################################### -->
123+
<br/>
124+
125+
# Example (with spring boot)
126+
127+
nothing.
128+
129+
130+
131+
132+
133+
<!-- ###################################################################################################################################### -->
134+
<!-- ###################################################################################################################################### -->
135+
<!-- ###################################################################################################################################### -->
136+
<br/>
137+
138+
### 참고자료
139+
140+
시작하기
5141
https://www.graalvm.org/latest/docs/getting-started/
142+
143+
native-image 명령어도 설치해야함
144+
https://www.graalvm.org/22.0/reference-manual/native-image/
145+
146+
### NoClassDefFoundError
147+
주의점! 예제를 만들때 `package`경로가 들어가지 않도록 주의한다.
148+
Link: https://stackoverflow.com/questions/17973970/how-can-i-solve-java-lang-noclassdeffounderror
149+
```shell
150+
   ~/Doc/GitHub/SpringExample/graalvm-example/src/main/java/graalvm/graalvmexample    GraalVM +11 !4 ?43  native-image HelloWorld  ✔  14:28:10 
151+
========================================================================================================================
152+
GraalVM Native Image: Generating 'helloworld' (executable)...
153+
========================================================================================================================
154+
[1/8] Initializing... (0.0s @ 0.07GB)
155+
156+
The build process encountered an unexpected error:
157+
158+
> java.lang.NoClassDefFoundError: HelloWorld (wrong name: graalvm/graalvmexample/HelloWorld)
159+
160+
Please inspect the generated error report at:
161+
/Users/hyeon/Documents/GitHub/SpringExample/graalvm-example/src/main/java/graalvm/graalvmexample/svm_err_b_20240909T142820.972_pid24795.md
162+
163+
If you are unable to resolve this problem, please file an issue with the error report at:
164+
https://graalvm.org/support
165+
```
166+
167+
- 에러 내용상세: svm_err_b_20240909T142820.972_pid24795.md
168+
169+
### etc
170+
https://docs.spring.io/spring-boot/reference/packaging/native-image/index.html
171+
172+
https://www.baeldung.com/graal-java-jit-compiler
173+

graalvm-example/img_1.png

74 KB
Loading

graalvm-example/img_2.png

86.3 KB
Loading
Binary file not shown.
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
//package graalvm.graalvmexample;
2+
3+
public class HelloWorld {
4+
public static void main(String[] args) {
5+
System.out.println("HEllo World");
6+
}
7+
}
Lines changed: 138 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,138 @@
1+
# GraalVM Native Image Error Report
2+
3+
## Build Output
4+
5+
```
6+
========================================================================================================================
7+
GraalVM Native Image: Generating 'helloworld' (executable)...
8+
========================================================================================================================
9+
[1/8] Initializing... (0.0s @ 0.07GB)
10+
```
11+
12+
## Stack Trace
13+
14+
```java
15+
java.lang.NoClassDefFoundError: HelloWorld (wrong name: graalvm/graalvmexample/HelloWorld)
16+
at java.base/java.lang.ClassLoader.defineClass1(Native Method)
17+
at java.base/java.lang.ClassLoader.defineClass(ClassLoader.java:1023)
18+
at java.base/java.security.SecureClassLoader.defineClass(SecureClassLoader.java:150)
19+
at org.graalvm.nativeimage.builder/com.oracle.svm.hosted.NativeImageClassLoader.defineClass(NativeImageClassLoader.java:490)
20+
at org.graalvm.nativeimage.builder/com.oracle.svm.hosted.NativeImageClassLoader.findClassViaClassPath(NativeImageClassLoader.java:442)
21+
at org.graalvm.nativeimage.builder/com.oracle.svm.hosted.NativeImageClassLoader.loadClass(NativeImageClassLoader.java:629)
22+
at java.base/java.lang.ClassLoader.loadClass(ClassLoader.java:525)
23+
at java.base/java.lang.Class.forName0(Native Method)
24+
at java.base/java.lang.Class.forName(Class.java:529)
25+
at java.base/java.lang.Class.forName(Class.java:508)
26+
at org.graalvm.nativeimage.builder/com.oracle.svm.hosted.ImageClassLoader.forName(ImageClassLoader.java:299)
27+
at org.graalvm.nativeimage.builder/com.oracle.svm.hosted.ImageClassLoader.forName(ImageClassLoader.java:295)
28+
at org.graalvm.nativeimage.builder/com.oracle.svm.hosted.ImageClassLoader.forName(ImageClassLoader.java:304)
29+
at org.graalvm.nativeimage.builder/com.oracle.svm.hosted.NativeImageGeneratorRunner.buildImage(NativeImageGeneratorRunner.java:433)
30+
at org.graalvm.nativeimage.builder/com.oracle.svm.hosted.NativeImageGeneratorRunner.build(NativeImageGeneratorRunner.java:701)
31+
at org.graalvm.nativeimage.builder/com.oracle.svm.hosted.NativeImageGeneratorRunner.start(NativeImageGeneratorRunner.java:140)
32+
at org.graalvm.nativeimage.builder/com.oracle.svm.hosted.NativeImageGeneratorRunner.main(NativeImageGeneratorRunner.java:95)
33+
```
34+
35+
## GraalVM Setup
36+
37+
| Name | Value |
38+
| ---- | ----- |
39+
| Java version | `22.0.2+9` |
40+
| Vendor version | `Oracle GraalVM 22.0.2+9.1` |
41+
| Runtime version | `22.0.2+9-jvmci-b01` |
42+
<details>
43+
<summary>GraalVM <code>release</code> file</summary>
44+
45+
```
46+
IMPLEMENTOR="Oracle Corporation"
47+
JAVA_RUNTIME_VERSION="22.0.2+9-jvmci-b01"
48+
JAVA_VERSION="22.0.2"
49+
JAVA_VERSION_DATE="2024-07-16"
50+
LIBC="default"
51+
MODULES="java.base java.logging java.management jdk.internal.vm.ci jdk.unsupported org.graalvm.collections jdk.management org.graalvm.truffle.compiler org.graalvm.word jdk.graal.compiler com.oracle.graal.graal_enterprise org.graalvm.nativeimage com.oracle.svm.enterprise.truffle com.oracle.svm.extraimage_enterprise java.compiler java.datatransfer java.xml java.prefs java.desktop java.instrument java.security.sasl java.naming java.rmi java.management.rmi java.net.http java.scripting java.security.jgss java.transaction.xa java.sql java.sql.rowset java.xml.crypto java.se java.smartcardio jdk.accessibility jdk.internal.jvmstat jdk.attach jdk.charsets jdk.internal.opt jdk.zipfs jdk.compiler jdk.crypto.cryptoki jdk.crypto.ec jdk.dynalink jdk.internal.ed jdk.editpad jdk.graal.compiler.management jdk.hotspot.agent jdk.httpserver jdk.incubator.vector jdk.internal.le jdk.jartool jdk.javadoc jdk.jcmd jdk.management.agent jdk.jconsole jdk.jdeps jdk.jdwp.agent jdk.jdi jdk.jfr jdk.jlink jdk.jpackage jdk.jshell jdk.jsobject jdk.jstatd jdk.localedata jdk.management.jfr jdk.naming.dns jdk.naming.rmi jdk.net jdk.nio.mapmode jdk.random jdk.sctp jdk.security.auth jdk.security.jgss jdk.unsupported.desktop jdk.xml.dom org.graalvm.extraimage.builder org.graalvm.extraimage.librarysupport org.graalvm.nativeimage.llvm"
52+
OS_ARCH="aarch64"
53+
OS_NAME="Darwin"
54+
SOURCE=".:git:6e8795b808d5 open:git:e7acb97c043d labsjdk-builder:b4692d7d77087d1c90eed166079d74bfbb6a706f compiler:1f72d5384cbf5a744b8284f874ad77947d2710bc graal-enterprise:16fd2fe15b348fc7f779dc5ebb85ad6ae9f3c98b java-benchmarks:1f72d5384cbf5a744b8284f874ad77947d2710bc regex:1f72d5384cbf5a744b8284f874ad77947d2710bc sdk:1f72d5384cbf5a744b8284f874ad77947d2710bc substratevm:1f72d5384cbf5a744b8284f874ad77947d2710bc substratevm-enterprise:16fd2fe15b348fc7f779dc5ebb85ad6ae9f3c98b substratevm-enterprise-gcs:30f83136f0f3ec80702f8b73cf167851ac9ebb2a tools:1f72d5384cbf5a744b8284f874ad77947d2710bc truffle:1f72d5384cbf5a744b8284f874ad77947d2710bc vm:1f72d5384cbf5a744b8284f874ad77947d2710bc vm-enterprise:16fd2fe15b348fc7f779dc5ebb85ad6ae9f3c98b"
55+
GRAALVM_VERSION="24.0.2"
56+
COMMIT_INFO={"compiler": {"commit.committer": "Marouane El Hallaoui <marouane.el.hallaoui@oracle.com>", "commit.committer-ts": 1720004771, "commit.rev": "1f72d5384cbf5a744b8284f874ad77947d2710bc"}, "graal-enterprise": {"commit.committer": "Marouane El Hallaoui <marouane.el.hallaoui@oracle.com>", "commit.committer-ts": 1720015242, "commit.rev": "16fd2fe15b348fc7f779dc5ebb85ad6ae9f3c98b"}, "java-benchmarks": {"commit.committer": "Marouane El Hallaoui <marouane.el.hallaoui@oracle.com>", "commit.committer-ts": 1720004771, "commit.rev": "1f72d5384cbf5a744b8284f874ad77947d2710bc"}, "regex": {"commit.committer": "Marouane El Hallaoui <marouane.el.hallaoui@oracle.com>", "commit.committer-ts": 1720004771, "commit.rev": "1f72d5384cbf5a744b8284f874ad77947d2710bc"}, "sdk": {"commit.committer": "Marouane El Hallaoui <marouane.el.hallaoui@oracle.com>", "commit.committer-ts": 1720004771, "commit.rev": "1f72d5384cbf5a744b8284f874ad77947d2710bc"}, "substratevm": {"commit.committer": "Marouane El Hallaoui <marouane.el.hallaoui@oracle.com>", "commit.committer-ts": 1720004771, "commit.rev": "1f72d5384cbf5a744b8284f874ad77947d2710bc"}, "substratevm-enterprise": {"commit.committer": "Marouane El Hallaoui <marouane.el.hallaoui@oracle.com>", "commit.committer-ts": 1720015242, "commit.rev": "16fd2fe15b348fc7f779dc5ebb85ad6ae9f3c98b"}, "substratevm-enterprise-gcs": {"commit.committer": "Christian Haeubl <christian.haeubl@oracle.com>", "commit.committer-ts": 1706086263, "commit.rev": "30f83136f0f3ec80702f8b73cf167851ac9ebb2a"}, "tools": {"commit.committer": "Marouane El Hallaoui <marouane.el.hallaoui@oracle.com>", "commit.committer-ts": 1720004771, "commit.rev": "1f72d5384cbf5a744b8284f874ad77947d2710bc"}, "truffle": {"commit.committer": "Marouane El Hallaoui <marouane.el.hallaoui@oracle.com>", "commit.committer-ts": 1720004771, "commit.rev": "1f72d5384cbf5a744b8284f874ad77947d2710bc"}, "vm": {"commit.committer": "Marouane El Hallaoui <marouane.el.hallaoui@oracle.com>", "commit.committer-ts": 1720004771, "commit.rev": "1f72d5384cbf5a744b8284f874ad77947d2710bc"}, "vm-enterprise": {"commit.committer": "Marouane El Hallaoui <marouane.el.hallaoui@oracle.com>", "commit.committer-ts": 1720015242, "commit.rev": "16fd2fe15b348fc7f779dc5ebb85ad6ae9f3c98b"}}
57+
```
58+
59+
</details>
60+
61+
## Builder Setup
62+
63+
<details>
64+
<summary>Class path</summary>
65+
66+
```
67+
/Users/hyeon/Documents/GitHub/SpringExample/graalvm-example/src/main/java/graalvm/graalvmexample
68+
```
69+
70+
</details>
71+
72+
<details>
73+
<summary>Module path</summary>
74+
75+
```
76+
/Users/hyeon/.sdkman/candidates/java/22.0.2-graal/lib/svm/library-support.jar
77+
/Users/hyeon/.sdkman/candidates/java/22.0.2-graal/lib/svm/builder/svm.jar
78+
/Users/hyeon/.sdkman/candidates/java/22.0.2-graal/lib/svm/builder/native-image-base.jar
79+
/Users/hyeon/.sdkman/candidates/java/22.0.2-graal/lib/svm/builder/objectfile.jar
80+
/Users/hyeon/.sdkman/candidates/java/22.0.2-graal/lib/svm/builder/svm-enterprise.jar
81+
/Users/hyeon/.sdkman/candidates/java/22.0.2-graal/lib/svm/builder/svm-foreign.jar
82+
/Users/hyeon/.sdkman/candidates/java/22.0.2-graal/lib/svm/builder/pointsto.jar
83+
```
84+
85+
</details>
86+
87+
<details>
88+
<summary>Builder arguments</summary>
89+
90+
```
91+
-H:CLibraryPath=/Users/hyeon/.sdkman/candidates/java/22.0.2-graal/lib/svm/clibraries/darwin-aarch64
92+
-H:Path@driver=/Users/hyeon/Documents/GitHub/SpringExample/graalvm-example/src/main/java/graalvm/graalvmexample
93+
-H:Class@explicit main-class=HelloWorld
94+
-H:Name@main-class lower case as image name=helloworld
95+
-H:ImageBuildID@driver=afe85bb4-cac4-22f3-b447-8af426d752bb
96+
-H:Features@jar:file:///Users/hyeon/.sdkman/candidates/java/22.0.2-graal/lib/svm/library-support.jar!/META-INF/native-image/com.oracle.svm/thirdparty/native-image.properties+api=com.oracle.svm.thirdparty.gson.GsonFeature
97+
-H:Features@jar:file:///Users/hyeon/.sdkman/candidates/java/22.0.2-graal/lib/svm/library-support.jar!/META-INF/native-image/com.oracle.svm/polyglot/native-image.properties+api=com.oracle.svm.polyglot.groovy.GroovyIndyInterfaceFeature,com.oracle.svm.polyglot.scala.ScalaFeature
98+
-H:Color@driver=always
99+
-H:+BuildOutputProgress@driver
100+
-H:+BuildOutputLinks@driver
101+
```
102+
103+
</details>
104+
105+
<details>
106+
<summary>Builder properties</summary>
107+
108+
```
109+
-Dcom.oracle.graalvm.isaot=true
110+
-Dgraalvm.ForcePolyglotInvalid=true
111+
-Dgraalvm.locatorDisabled=true
112+
-Djava.awt.headless=true
113+
-Djava.lang.invoke.InnerClassLambdaMetafactory.initializeLambdas=false
114+
-Djava.lang.invoke.MethodHandle.DONT_INLINE_THRESHOLD=-1
115+
-Djava.lang.invoke.MethodHandle.PROFILE_GWT=false
116+
-Djava.system.class.loader=com.oracle.svm.hosted.NativeImageSystemClassLoader
117+
-Djdk.internal.lambda.disableEagerInitialization=true
118+
-Djdk.internal.lambda.eagerlyInitialize=false
119+
-Djdk.module.main=org.graalvm.nativeimage.builder
120+
-Djdk.reflect.useOldSerializableConstructor=true
121+
-Dorg.graalvm.vendor=Oracle Corporation
122+
-Dorg.graalvm.vendorurl=https://www.graalvm.org/
123+
-Dorg.graalvm.vendorversion=Oracle GraalVM 22.0.2+9.1
124+
-Dorg.graalvm.version=24.0.2
125+
-Dtruffle.TruffleRuntime=com.oracle.truffle.api.impl.DefaultTruffleRuntime
126+
-Dtruffle.TrustAllTruffleRuntimeProviders=true
127+
```
128+
129+
</details>
130+
131+
<details>
132+
<summary>Features enabled</summary>
133+
134+
```
135+
*FeatureHandler not present.*
136+
```
137+
138+
</details>

0 commit comments

Comments
 (0)