เกี่ยวกับ Codelab นี้
1 ภาพรวม
ใน Codelab นี้ เราจะเรียนรู้เกี่ยวกับโปรเจ็กต์ Spring Native, การสร้างแอปที่ใช้แอป และทำให้แอปใช้งานได้ใน Google Cloud
เราจะดูคอมโพเนนต์ของโปรเจ็กต์ ประวัติล่าสุดของโปรเจ็กต์ กรณีการใช้งานบางส่วน และขั้นตอนที่จำเป็นในการใช้โปรเจ็กต์ในโปรเจ็กต์ของคุณ
ปัจจุบันโปรเจ็กต์เนทีฟในฤดูใบไม้ผลิอยู่ในขั้นทดลอง ดังนั้นจึงต้องมีการกำหนดค่าเฉพาะบางอย่างเพื่อเริ่มต้นใช้งาน อย่างไรก็ตาม ตามที่ได้ประกาศไปในงาน SpringOne 2021 ว่า Spring Native จะผสานรวมเข้ากับ Spring Framework 6.0 และ Spring Boot 3.0 ที่มีการสนับสนุนระดับเฟิร์สคลาส ดังนั้นนี่จึงเป็นโอกาสเหมาะที่จะตรวจสอบโปรเจ็กต์อย่างละเอียดในช่วง 2-3 เดือนก่อนการเปิดตัว
แม้ว่าการคอมไพล์แบบทันทีจะได้รับการเพิ่มประสิทธิภาพอย่างมากสำหรับสิ่งต่างๆ เช่น กระบวนการที่ใช้เวลานาน แต่ก็มีกรณีการใช้งานบางกรณีที่แอปพลิเคชันคอมไพล์ล่วงหน้าจะทำงานได้ดีกว่า ซึ่งเราจะกล่าวถึงใน Codelab
คุณจะได้เรียนรู้วิธีต่อไปนี้
- ใช้ Cloud Shell
- เปิดใช้ Cloud Run API
- สร้างและทำให้แอป Spring Native ใช้งานได้
- ทำให้แอปดังกล่าวใช้งานได้ใน Cloud Run
สิ่งที่คุณต้องมี
- โปรเจ็กต์ Google Cloud Platform ที่มีบัญชีสำหรับการเรียกเก็บเงิน GCP ที่ใช้งานอยู่
- ติดตั้ง gcloud cli แล้ว หรือสิทธิ์เข้าถึง Cloud Shell
- ทักษะพื้นฐาน Java + XML
- ความรู้เกี่ยวกับคำสั่งทั่วไปของ Linux
แบบสำรวจ
คุณจะใช้บทแนะนำนี้อย่างไร
คุณจะให้คะแนนประสบการณ์การใช้งาน Java อย่างไร
คุณจะให้คะแนนความพึงพอใจในการใช้บริการ Google Cloud อย่างไร
2 ข้อมูลเบื้องต้น
โปรเจ็กต์ Spring Native จะใช้เทคโนโลยีหลายๆ แบบเพื่อมอบประสิทธิภาพของแอปพลิเคชันแบบเนทีฟให้แก่นักพัฒนาซอฟต์แวร์
เราขอแนะนำให้ทำความเข้าใจกับเทคโนโลยีคอมโพเนนต์บางส่วนเหล่านี้ สิ่งที่ทำให้เกิดเรา และวิธีที่เทคโนโลยีดังกล่าวทำงานร่วมกันที่นี่ เพื่อทำความเข้าใจอย่างถ่องแท้
วิดีโอรวมคลิป AOT
เมื่อนักพัฒนาซอฟต์แวร์เรียกใช้ Javac ตามปกติในเวลาคอมไพล์ ระบบจะคอมไพล์ซอร์สโค้ด .java ของเราเป็นไฟล์ .class ซึ่งเขียนเป็นไบต์โค้ด ไบต์โค้ดนี้มีไว้เพื่อให้ Java Virtual Machine เข้าใจเท่านั้น ดังนั้น JVM จะต้องตีความโค้ดนี้บนเครื่องอื่นเพื่อให้เราเรียกใช้โค้ดได้
กระบวนการนี้ทำให้เรามีความสามารถในการถ่ายโอนแบบลายเซ็นของ Java ทำให้เราสามารถ "เขียนครั้งเดียวและทำงานได้ทุกที่" แต่มันมีค่าใช้จ่ายสูงเมื่อเทียบกับการเรียกใช้โค้ดแบบเนทีฟ
โชคดีที่การใช้งาน JVM ส่วนใหญ่ใช้การคอมไพล์แบบทันท่วงทีเพื่อลดค่าใช้จ่ายในการตีความนี้ ซึ่งทำได้โดยการนับการเรียกสำหรับฟังก์ชัน และหากมีการเรียกใช้บ่อยพอที่จะผ่านเกณฑ์ ( 10,000 ครั้งโดยค่าเริ่มต้น) ระบบจะคอมไพล์เป็นโค้ดแบบเนทีฟขณะรันไทม์เพื่อป้องกันการตีความค่าใช้จ่ายที่แพงกว่า
การคอมไพล์แบบล่วงหน้าจะใช้วิธีตรงกันข้าม โดยการรวบรวมโค้ดที่เข้าถึงได้ทั้งหมดลงในไฟล์ปฏิบัติการแบบเนทีฟในเวลาคอมไพล์ วิธีนี้ลดความสามารถในการถ่ายโอนได้เพื่อประหยัดหน่วยความจำและประสิทธิภาพอื่นๆ ที่เพิ่มขึ้นในขณะทำงาน
แน่นอนว่านี่เป็นข้อดี และจะไม่คุ้มค่ากับการต้องรับ อย่างไรก็ตาม การรวบรวม AOT อาจมีประสิทธิภาพได้ในบางกรณี เช่น
- แอปพลิเคชันที่มีอายุสั้นโดยที่เวลาเริ่มต้นเป็นสิ่งสำคัญ
- สภาพแวดล้อมที่มีหน่วยความจำจำกัดสูงซึ่ง JIT อาจใช้ต้นทุนมากเกินไป
อันที่จริงแล้ว คลิปรวม AOT ได้รับการนำเสนอเป็นฟีเจอร์ทดลองใน JDK 9 แม้ว่าการติดตั้งใช้งานนี้จะมีค่าใช้จ่ายในการดูแลรักษาสูงและไม่ค่อยถูกจับต้อง ระบบจึงทยอยนำออกใน Java 17 เพื่อประโยชน์ของนักพัฒนาซอฟต์แวร์ที่ใช้ GraalVM เท่านั้น
GraalVM
GraalVM คือการกระจาย JDK แบบโอเพนซอร์สที่ได้รับการเพิ่มประสิทธิภาพขั้นสูง พร้อมเวลาเปิดเครื่องที่รวดเร็วมาก การคอมไพล์รูปภาพแบบ AOT ในเครื่อง และความสามารถด้านภาษาศาสตร์ที่ทำให้นักพัฒนาซอฟต์แวร์ผสมผสานภาษาต่างๆ ไว้ในแอปพลิเคชันเดียวได้
GraalVM อยู่ระหว่างการพัฒนา เพิ่มความสามารถใหม่ๆ และปรับปรุงความสามารถที่มีอยู่อยู่เสมอ ฉันจึงขอให้นักพัฒนาซอฟต์แวร์ติดตามความคืบหน้าอยู่เสมอ
เหตุการณ์สำคัญล่าสุดมีดังนี้
- เอาต์พุตบิลด์ใหม่สำหรับอิมเมจเนทีฟที่ใช้งานง่าย ( 18-01-2021)
- การรองรับ Java 17 ( 2022-01-18)
- เปิดใช้การคอมไพล์แบบหลายชั้นโดยค่าเริ่มต้นเพื่อปรับปรุงเวลาคอมไพล์แบบหลายภาษา ( 20-04-2021)
เนทีฟช่วงฤดูใบไม้ผลิ
พูดง่ายๆ ก็คือ Spring Native ทำให้สามารถใช้คอมไพเลอร์รูปภาพแบบเนทีฟของ GraalVM เพื่อเปลี่ยนแอปพลิเคชัน Spring เป็นไฟล์สั่งการที่มาพร้อมเครื่อง
กระบวนการนี้จะต้องมีการวิเคราะห์แอปพลิเคชันแบบคงที่ในเวลาคอมไพล์เพื่อค้นหาวิธีการทั้งหมดในแอปพลิเคชันที่เข้าถึงได้จากจุดแรกเข้า
ซึ่งเป็นการสร้าง "โลกปิด" ขึ้นมาโดยหลัก แนวคิดของแอปพลิเคชันของคุณ ซึ่งจะถือว่ารู้โค้ดทั้งหมดในเวลาคอมไพล์ และจะไม่อนุญาตให้โหลดโค้ดใหม่ขณะรันไทม์
โปรดทราบว่าการสร้างรูปภาพในเครื่องเป็นกระบวนการที่ใช้หน่วยความจำมาก ซึ่งใช้เวลานานกว่าการคอมไพล์แอปพลิเคชันทั่วไป และกำหนดข้อจำกัดในบางแง่มุมของ Java
ในบางกรณี คุณไม่จำเป็นต้องเปลี่ยนแปลงโค้ดเพื่อให้แอปพลิเคชันทำงานร่วมกับ Spring Native ได้ อย่างไรก็ตาม บางสถานการณ์จำเป็นต้องมีการกำหนดค่าเนทีฟเฉพาะเพื่อให้ทำงานได้อย่างถูกต้อง ซึ่งในสถานการณ์เหล่านั้น โฆษณาเนทีฟในฤดูใบไม้ผลิมักจะให้คำแนะนำเนทีฟเพื่อลดความซับซ้อนของกระบวนการนี้
3 การตั้งค่า/งานล่วงหน้า
ก่อนที่จะเริ่มใช้โฆษณาเนทีฟในฤดูใบไม้ผลิ เราจะต้องสร้างและทำให้แอปใช้งานได้เพื่อสร้างเกณฑ์พื้นฐานด้านประสิทธิภาพที่เราจะนำไปเปรียบเทียบกับเวอร์ชันเนทีฟในภายหลังได้
1. สร้างโปรเจ็กต์
เราจะเริ่มต้นด้วยการรับแอปจาก start.spring.io:
curl https://start.spring.io/starter.zip -d dependencies=web \ -d javaVersion=11 \ -d bootVersion=2.6.4 -o io-native-starter.zip
แอปเริ่มต้นนี้ใช้ Spring Boot 2.6.4 ซึ่งเป็นเวอร์ชันล่าสุดที่โปรเจ็กต์ Spring-native รองรับในขณะที่เขียน
โปรดทราบว่านับตั้งแต่การเปิดตัว GraalVM 21.0.3 คุณสามารถใช้ Java 17 สำหรับตัวอย่างนี้ได้เช่นกัน เราจะยังคงใช้ Java 11 สำหรับบทแนะนำนี้เพื่อลดการกำหนดค่าที่เกี่ยวข้อง
เมื่อเรามีไฟล์ ZIP ในบรรทัดคำสั่งแล้ว เราก็สามารถสร้างไดเรกทอรีย่อยสำหรับโปรเจ็กต์ของเรา และแตกโฟลเดอร์ในนั้น:
mkdir spring-native cd spring-native unzip ../io-native-starter.zip
2. การเปลี่ยนแปลงโค้ด
หลังจากเปิดโปรเจ็กต์แล้ว เราจะเพิ่มสัญญาณแห่งชีวิตอย่างรวดเร็วและแสดงประสิทธิภาพของโฆษณาเนทีฟในฤดูใบไม้ผลิเมื่อเรียกใช้
แก้ไข DemoApplication.java ให้ตรงกับคำสั่งนี้
package com.example.demo;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.event.ApplicationReadyEvent;
import org.springframework.context.event.EventListener;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.RestController;
import java.time.Duration;
import java.time.Instant;
@RestController
@SpringBootApplication
public class DemoApplication {
private static Instant startTime;
private static Instant readyTime;
public static void main(String[] args) {
startTime = Instant.now();
SpringApplication.run(DemoApplication.class, args);
}
@GetMapping("/")
public String index() {
return "Time between start and ApplicationReadyEvent: "
+ Duration.between(startTime, readyTime).toMillis()
+ "ms";
}
@EventListener(ApplicationReadyEvent.class)
public void ready() {
readyTime = Instant.now();
}
}
ในขั้นนี้แอปพื้นฐานของเราพร้อมแล้ว ดังนั้นให้สร้างอิมเมจและเรียกใช้ในเครื่องเพื่อทราบถึงช่วงเวลาเริ่มต้นก่อนที่เราจะแปลงแอปเป็นแอปพลิเคชันที่มาพร้อมเครื่อง
วิธีสร้างรูปภาพ
mvn spring-boot:build-image
คุณยังใช้ docker images demo
เพื่อให้ทราบขนาดของรูปภาพพื้นฐานได้โดยทำดังนี้
วิธีเรียกใช้แอป
docker run --rm -p 8080:8080 demo:0.0.1-SNAPSHOT
3. ทำให้แอปพื้นฐานใช้งานได้
ตอนนี้เรามีแอปแล้ว เราจะทำให้ใช้งานได้และจดบันทึกเวลาที่เราจะนำไปเปรียบเทียบกับเวลาเริ่มต้นของแอปที่มาพร้อมเครื่องในภายหลัง
มีหลายโฮสติ้งเนื้อหาของคุณ ทั้งนี้ขึ้นอยู่กับประเภทแอปพลิเคชันที่คุณสร้าง
อย่างไรก็ตาม เนื่องจากตัวอย่างของเราเป็นเว็บแอปพลิเคชันที่ง่ายและไม่ซับซ้อน เราจึงสามารถทำให้ทุกอย่างเรียบง่ายและใช้ Cloud Run ได้
หากติดตามด้วยเครื่องของคุณเอง โปรดตรวจสอบว่าได้ติดตั้งและอัปเดตเครื่องมือ gcloud CLI แล้ว
หากใช้ Cloud Shell ซึ่งจะได้รับการดูแลทั้งหมด และคุณสามารถเรียกใช้สิ่งต่อไปนี้ในไดเรกทอรีต้นทางได้
gcloud run deploy
4 การกำหนดค่าแอปพลิเคชัน
1. การกำหนดค่าที่เก็บ Maven ของเรา
เนื่องจากโปรเจ็กต์นี้ยังคงอยู่ในระยะทดลอง เราจึงจะต้องกำหนดค่าแอปให้ค้นหาอาร์ติแฟกต์ทดลองได้ ซึ่งไม่มีให้บริการในที่เก็บส่วนกลางของ Maven
ซึ่งรวมถึงการเพิ่มองค์ประกอบต่อไปนี้ลงใน pom.xml ของเรา ซึ่งคุณดำเนินการได้ในตัวแก้ไขที่ต้องการ
เพิ่มส่วน ที่เก็บข้อมูล และ PluginRepositories ต่อไปนี้ใน Pom ของเรา:
<repositories>
<repository>
<id>spring-release</id>
<name>Spring release</name>
<url>https://repo.spring.io/release</url>
</repository>
</repositories>
<pluginRepositories>
<pluginRepository>
<id>spring-release</id>
<name>Spring release</name>
<url>https://repo.spring.io/release</url>
</pluginRepository>
</pluginRepositories>
2. การเพิ่มทรัพยากร Dependency
ถัดไป ให้เพิ่มทรัพยากร Dependency สำหรับฤดูใบไม้ผลิซึ่งจำเป็นสำหรับการเรียกใช้แอปพลิเคชัน Spring เป็นรูปภาพเนทีฟ หมายเหตุ: ขั้นตอนนี้ไม่จำเป็นหากใช้ Gradle
<dependencies>
<!-- ... -->
<dependency>
<groupId>org.springframework.experimental</groupId>
<artifactId>spring-native</artifactId>
<version>0.11.2</version>
</dependency>
</dependencies>
3. การเพิ่ม/เปิดใช้ปลั๊กอิน
ตอนนี้ให้เพิ่มปลั๊กอิน AOT เพื่อปรับปรุงความเข้ากันได้และฟุตพริ้นท์ของรูปภาพดั้งเดิม ( อ่านเพิ่มเติม)
<plugins>
<!-- ... -->
<plugin>
<groupId>org.springframework.experimental</groupId>
<artifactId>spring-aot-maven-plugin</artifactId>
<version>0.11.2</version>
<executions>
<execution>
<id>generate</id>
<goals>
<goal>generate</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
ตอนนี้เราจะอัปเดตปลั๊กอิน spring-boot-maven-plugin เพื่อเปิดใช้การรองรับอิมเมจในเครื่องและใช้เครื่องมือสร้าง paketo เพื่อสร้างอิมเมจเนทีฟ
<plugins>
<!-- ... -->
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
<configuration>
<image>
<builder>paketobuildpacks/builder:tiny</builder>
<env>
<BP_NATIVE_IMAGE>true</BP_NATIVE_IMAGE>
</env>
</image>
</configuration>
</plugin>
</plugins>
โปรดทราบว่ารูปภาพเครื่องมือสร้างขนาดเล็กเป็นเพียงหนึ่งในตัวเลือกหลายๆ ตัวเลือก ตัวเลือกนี้เหมาะสำหรับ Use Case ของเราเพราะมีไลบรารีและยูทิลิตีเพิ่มเติมน้อยมาก ซึ่งช่วยลดพื้นที่ในการโจมตี
ตัวอย่างเช่น ถ้าคุณกำลังสร้างแอปที่ต้องเข้าถึงไลบรารี C ทั่วไปบางรายการ และคุณยังไม่แน่ใจเกี่ยวกับข้อกำหนดของแอป เครื่องมือสร้างแบบเต็มรูปแบบอาจเหมาะสมกว่า
5 สร้างและเรียกใช้แอปที่มาพร้อมเครื่อง
เมื่อทุกอย่างพร้อมแล้ว เราควรจะสามารถสร้างอิมเมจและเรียกใช้แอปที่มาพร้อมเครื่องซึ่งคอมไพล์ได้
ก่อนเรียกใช้บิลด์ โปรดคำนึงถึงสิ่งต่อไปนี้
- การดำเนินการนี้จะใช้เวลามากกว่าบิลด์ปกติ (2-3 นาที)
- กระบวนการบิลด์นี้ใช้หน่วยความจำจำนวนมาก (ไม่กี่กิกะไบต์)
- กระบวนการบิลด์นี้กำหนดให้เข้าถึง Daemon ของ Docker ได้
- ในตัวอย่างนี้เรากำลังทำกระบวนการด้วยตนเอง คุณยังสามารถกำหนดค่าเฟสของบิลด์ให้ทริกเกอร์โปรไฟล์บิลด์เนทีฟโดยอัตโนมัติได้ด้วย
วิธีสร้างรูปภาพ
mvn spring-boot:build-image
เมื่อสร้างเสร็จแล้ว เราพร้อมที่จะเห็นการทำงานของแอปที่มาพร้อมเครื่องแล้ว
วิธีเรียกใช้แอป
docker run --rm -p 8080:8080 demo:0.0.1-SNAPSHOT
ณ จุดนี้ เราอยู่ในตำแหน่งที่ยอดเยี่ยมที่จะได้เห็นสมการการประยุกต์ใช้แบบเดิมทั้ง 2 ด้านแล้ว
เราไม่ได้ให้เวลาและมีการใช้หน่วยความจำเพิ่มขึ้นเล็กน้อยในเวลาคอมไพล์ แต่ในทางกลับกัน เราได้รับแอปพลิเคชันที่เริ่มทำงานได้เร็วกว่ามากและใช้หน่วยความจำน้อยลงมาก (ขึ้นอยู่กับปริมาณงาน)
หากเราเรียกใช้ docker images demo
เพื่อเปรียบเทียบขนาดของรูปภาพต้นฉบับกับต้นฉบับ เราจะเห็นการลดลงอย่างมาก
นอกจากนี้เรายังควรทราบด้วยว่าในกรณีการใช้งานที่ซับซ้อนมากขึ้น จะต้องมีการแก้ไขเพิ่มเติมเพื่อแจ้งให้คอมไพเลอร์ AOT ทราบถึงสิ่งที่แอปของคุณจะทำในระหว่างรันไทม์ ด้วยเหตุนี้ ภาระงานที่คาดเดาได้บางอย่าง (เช่น งานแบบกลุ่ม) อาจเหมาะกับกรณีนี้มาก แต่หากภาระงานอื่นๆ อาจใช้เวลานานกว่านี้
6 การทำให้แอปที่มาพร้อมเครื่องของเราใช้งานได้
ในการทำให้แอปของเราใช้งานได้ใน Cloud Run เราจะต้องนำอิมเมจในเครื่องเข้าสู่เครื่องมือจัดการแพ็กเกจ เช่น Artifact Registry
1. กำลังเตรียมที่เก็บ Docker
เราสามารถเริ่มกระบวนการนี้โดยการสร้างที่เก็บ:
gcloud artifacts repositories create native-image-docker-repo --repository-format=docker \
--location=us-central1 --description="Repository for our native images"
ถัดไป เราต้องการตรวจสอบว่าผ่านการตรวจสอบสิทธิ์เพื่อพุชไปยังรีจิสทรีใหม่แล้ว
ซึ่ง gcloud CLI จะช่วยลดความซับซ้อนของกระบวนการดังกล่าวไปเล็กน้อยได้โดยทำดังนี้
gcloud auth configure-docker us-central1-docker.pkg.dev
2. พุชอิมเมจของเราไปยัง Artifact Registry
ต่อไป เราจะติดแท็กรูปภาพของเรา ดังนี้
export PROJECT_ID=$(gcloud config list --format 'value(core.project)')
docker tag demo:0.0.1-SNAPSHOT \
us-central1-docker.pkg.dev/$PROJECT_ID/native-image-docker-repo/quickstart-image:tag2
จากนั้นเราจะใช้ docker push
เพื่อส่งไปยัง Artifact Registry ดังนี้
docker push us-central1-docker.pkg.dev/$PROJECT_ID/native-image-docker-repo/quickstart-image:tag2
3. การทำให้ใช้งานได้กับ Cloud Run
ตอนนี้เราพร้อมที่จะทำให้อิมเมจที่เราจัดเก็บไว้ใน Artifact Registry ใช้งานได้ไปยัง Cloud Run แล้ว โดยทำดังนี้
gcloud run deploy --image us-central1-docker.pkg.dev/$PROJECT_ID/native-image-docker-repo/quickstart-image:tag2
เนื่องจากเราได้สร้างและปรับใช้แอปของเราเป็นอิมเมจในเครื่อง เราจึงมั่นใจได้ว่าแอปพลิเคชันของเราใช้ต้นทุนด้านโครงสร้างพื้นฐานได้อย่างยอดเยี่ยมในขณะที่ทำงาน
คุณสามารถเปรียบเทียบเวลาเริ่มต้นของแอปพื้นฐานของเรากับเวลาเริ่มต้นของแอปใหม่ๆ ได้ด้วยตัวคุณเอง
7 สรุป/ล้างข้อมูล
ขอแสดงความยินดีกับการสร้างและทำให้แอปพลิเคชัน Spring Native ใช้งานได้ใน Google Cloud
เราหวังว่าบทแนะนำนี้จะช่วยส่งเสริมให้คุณทำความคุ้นเคยกับโปรเจ็กต์ Spring Native และอย่าลืมคำนึงถึงสิ่งนี้หากสิ่งนี้ตอบสนองความต้องการของคุณในอนาคต
ไม่บังคับ: ล้างข้อมูลและ/หรือปิดใช้บริการ
ไม่ว่าคุณจะสร้างโปรเจ็กต์ Google Cloud สําหรับ Codelab นี้หรือใช้โปรเจ็กต์ที่มีอยู่ซ้ำ โปรดระมัดระวังเพื่อหลีกเลี่ยงการเรียกเก็บเงินที่ไม่จำเป็นจากทรัพยากรที่เราใช้
คุณสามารถลบหรือปิดใช้บริการ Cloud Run ที่เราสร้าง ลบอิมเมจที่เราโฮสต์ไว้ หรือปิดทั้งโปรเจ็กต์
8 แหล่งข้อมูลเพิ่มเติม
แม้ว่าในตอนนี้โปรเจ็กต์ Spring Native จะเป็นโปรเจ็กต์ทดลองใหม่ๆ แต่ก็มีแหล่งข้อมูลดีๆ มากมายที่จะช่วยผู้ใช้นำร่องแก้ปัญหาและเข้ามามีส่วนร่วมได้ ดังนี้
แหล่งข้อมูลเพิ่มเติม
ด้านล่างนี้คือแหล่งข้อมูลออนไลน์ที่อาจเกี่ยวข้องกับบทแนะนำนี้
- ดูข้อมูลเพิ่มเติมเกี่ยวกับคำแนะนำเนทีฟ
- ดูข้อมูลเพิ่มเติมเกี่ยวกับ GraalVM
- วิธีมีส่วนร่วม
- ข้อผิดพลาดหน่วยความจำเต็มเมื่อสร้างรูปภาพเนทีฟ
- ข้อผิดพลาดเกี่ยวกับการเริ่มแอปพลิเคชันล้มเหลว
ใบอนุญาต
ผลงานนี้ได้รับอนุญาตภายใต้ใบอนุญาตทั่วไปครีเอทีฟคอมมอนส์แบบระบุแหล่งที่มา 2.0