1. खास जानकारी
इस कोडलैब में, हम Spring Native प्रोजेक्ट के बारे में जानेंगे. साथ ही, इसका इस्तेमाल करके एक ऐप्लिकेशन बनाएंगे और उसे Google Cloud पर डिप्लॉय करेंगे.
हम इसके कॉम्पोनेंट, प्रोजेक्ट के हाल ही के इतिहास, इस्तेमाल के कुछ उदाहरणों, और आपके प्रोजेक्ट में इसका इस्तेमाल करने के लिए ज़रूरी चरणों के बारे में जानेंगे.
फ़िलहाल, Spring Native प्रोजेक्ट एक्सपेरिमेंट के तौर पर उपलब्ध है. इसलिए, इसे शुरू करने के लिए कुछ खास कॉन्फ़िगरेशन की ज़रूरत होगी. हालांकि, SpringOne 2021 में यह एलान किया गया था कि Spring Native को Spring Framework 6.0 और Spring Boot 3.0 में बेहतरीन सपोर्ट के साथ इंटिग्रेट किया जाएगा. इसलिए, रिलीज़ होने से कुछ महीने पहले इस प्रोजेक्ट पर करीब से नज़र डालने का यह सही समय है.
जस्ट-इन-टाइम कंपाइलेशन को लंबी प्रोसेस जैसी चीज़ों के लिए बहुत अच्छी तरह से ऑप्टिमाइज़ किया गया है. हालांकि, इस्तेमाल के कुछ ऐसे मामले हैं जिनमें पहले से कंपाइल किए गए ऐप्लिकेशन बेहतर परफ़ॉर्म करते हैं. हम कोडलैब के दौरान इस बारे में चर्चा करेंगे.
आपको इनके बारे में जानकारी मिलेगी
- Cloud Shell का इस्तेमाल करना
- Cloud Run API को चालू करें
- Spring Native ऐप्लिकेशन बनाना और उसे डिप्लॉय करना
- ऐसे ऐप्लिकेशन को Cloud Run पर डिप्लॉय करना
आपको इन चीज़ों की ज़रूरत होगी
- चालू GCP बिलिंग खाते वाला Google Cloud Platform प्रोजेक्ट
- gcloud cli इंस्टॉल किया गया हो या Cloud Shell को ऐक्सेस करने की अनुमति हो
- Java और XML की बुनियादी जानकारी
- Linux की सामान्य कमांड के बारे में जानकारी होना
सर्वे
इस ट्यूटोरियल का इस्तेमाल कैसे किया जाएगा?
Java के साथ अपने अनुभव को आप क्या रेटिंग देंगे?
Google Cloud की सेवाओं को इस्तेमाल करने के अपने अनुभव को आप क्या रेटिंग देंगे?
2. बैकग्राउंड
Spring Native प्रोजेक्ट, डेवलपर को नेटिव ऐप्लिकेशन की परफ़ॉर्मेंस देने के लिए कई टेक्नोलॉजी का इस्तेमाल करता है.
Spring Native को पूरी तरह से समझने के लिए, इन कॉम्पोनेंट टेक्नोलॉजी के बारे में जानना ज़रूरी है. साथ ही, यह भी जानना ज़रूरी है कि ये टेक्नोलॉजी हमारे लिए क्या-क्या कर सकती हैं और ये एक साथ कैसे काम करती हैं.
AOT कंपाइलेशन
जब डेवलपर, कंपाइल करने के समय सामान्य तौर पर javac चलाते हैं, तो हमारा .java सोर्स कोड, .class फ़ाइलों में कंपाइल हो जाता है. ये फ़ाइलें बाइटकोड में लिखी जाती हैं. इस बाइटकोड को सिर्फ़ Java Virtual Machine समझ सकता है. इसलिए, हमें अपना कोड चलाने के लिए, JVM को इस कोड को अन्य मशीनों पर इंटरप्रेट करना होगा.
इस प्रोसेस की वजह से ही Java को पोर्टेबिलिटी की सुविधा मिलती है. इससे हमें "एक बार कोड लिखने और उसे हर जगह चलाने" की सुविधा मिलती है. हालांकि, नेटिव कोड चलाने की तुलना में यह प्रोसेस महंगी है.
हालांकि, JVM के ज़्यादातर वर्शन में, इस इंटरप्रेटेशन की लागत को कम करने के लिए, जस्ट-इन-टाइम कंपाइलेशन का इस्तेमाल किया जाता है. इसके लिए, किसी फ़ंक्शन के इनवोकेशन की गिनती की जाती है. अगर थ्रेशोल्ड ( डिफ़ॉल्ट रूप से 10,000) को पूरा करने के लिए, इसे काफ़ी बार इनवोक किया जाता है, तो इसे रन टाइम पर नेटिव कोड में कंपाइल किया जाता है, ताकि आगे महंगा इंटरप्रेटेशन न हो.
इसके उलट, कंपाइल टाइम पर सभी कोड को नेटिव एक्ज़ीक्यूटेबल में कंपाइल करने के लिए, ऐहड-ऑफ़-टाइम कंपाइलेशन का इस्तेमाल किया जाता है. यह रन टाइम में, मेमोरी की क्षमता और परफ़ॉर्मेंस को बेहतर बनाने के लिए पोर्टेबिलिटी को ट्रेड करता है.

हालांकि, यह एक तरह का समझौता है और हमेशा फ़ायदेमंद नहीं होता. हालांकि, कुछ मामलों में एओटी कंपाइलेशन का इस्तेमाल करना फ़ायदेमंद हो सकता है. जैसे:
- ऐसे ऐप्लिकेशन जो कम समय के लिए इस्तेमाल किए जाते हैं और जिनके स्टार्टअप का समय अहम होता है
- ऐसे एनवायरमेंट जहां मेमोरी की सीमा बहुत कम होती है और JIT का इस्तेमाल करने पर ज़्यादा खर्च आ सकता है
दिलचस्प बात यह है कि JDK 9 में, AOT कंपाइलेशन को एक्सपेरिमेंट के तौर पर उपलब्ध सुविधा के तौर पर पेश किया गया था. हालाँकि, इसे लागू करने में काफ़ी खर्च आता था और यह कभी लोकप्रिय नहीं हुआ. इसलिए, Java 17 में इसे हटा दिया गया. इसके बजाय, डेवलपर को सिर्फ़ GraalVM का इस्तेमाल करने की सलाह दी गई.
GraalVM
GraalVM, ओपन सोर्स JDK डिस्ट्रिब्यूशन है. इसे बहुत ज़्यादा ऑप्टिमाइज़ किया गया है. इसमें स्टार्टअप का समय बहुत कम होता है. साथ ही, इसमें एओटी नेटिव इमेज कंपाइलेशन और पॉलीग्लोट की सुविधाएं होती हैं. इनकी मदद से डेवलपर, एक ही ऐप्लिकेशन में कई भाषाओं को मिक्स कर सकते हैं.
GraalVM को लगातार बेहतर बनाया जा रहा है. इसमें नई सुविधाएं जोड़ी जा रही हैं और मौजूदा सुविधाओं को बेहतर बनाया जा रहा है. इसलिए, हम डेवलपर को सलाह देते हैं कि वे अपडेट के लिए बने रहें.
हाल ही की कुछ उपलब्धियां ये हैं:
- इस्तेमाल में आसान, नई नेटिव इमेज बिल्ड आउटपुट ( 18-01-2021)
- Java 17 के साथ काम करने की सुविधा ( 2022-01-18)
- एक से ज़्यादा टियर वाले कंपाइलेशन को डिफ़ॉल्ट रूप से चालू करना, ताकि अलग-अलग भाषाओं में लिखे गए कोड को कंपाइल करने में लगने वाले समय को कम किया जा सके ( 2021-04-20)
Spring Native
आसान शब्दों में कहें, तो Spring Native, Spring ऐप्लिकेशन को नेटिव एक्ज़ीक्यूटेबल में बदलने के लिए, GraalVM के native-image कंपाइलर का इस्तेमाल करने की सुविधा देता है.
इस प्रोसेस में, कंपाइल टाइम पर आपके ऐप्लिकेशन का स्टैटिक विश्लेषण किया जाता है. इससे आपके ऐप्लिकेशन में मौजूद उन सभी तरीकों का पता चलता है जिन तक एंट्री पॉइंट से पहुंचा जा सकता है.
इससे आपके ऐप्लिकेशन के लिए "क्लोज़्ड-वर्ल्ड" कॉन्सेप्ट बनता है. इसमें यह मान लिया जाता है कि कंपाइल टाइम पर सभी कोड की जानकारी है. साथ ही, रनटाइम पर कोई नया कोड लोड करने की अनुमति नहीं होती है.
यह ध्यान रखना ज़रूरी है कि नेटिव इमेज जनरेशन एक ऐसी प्रोसेस है जिसमें बहुत ज़्यादा मेमोरी की ज़रूरत होती है. इसमें किसी सामान्य ऐप्लिकेशन को कंपाइल करने में लगने वाले समय से ज़्यादा समय लगता है. साथ ही, यह Java के कुछ पहलुओं पर पाबंदियां लगाता है.
कुछ मामलों में, किसी ऐप्लिकेशन को Spring Native के साथ काम करने के लिए, कोड में कोई बदलाव करने की ज़रूरत नहीं होती. हालांकि, कुछ स्थितियों में नेटिव कॉन्फ़िगरेशन को ठीक से काम करने के लिए, खास कॉन्फ़िगरेशन की ज़रूरत होती है. ऐसी स्थितियों में, Spring Native अक्सर इस प्रोसेस को आसान बनाने के लिए नेटिव हिंट देता है.
3. सेटअप/प्रीवर्क
Spring Native को लागू करने से पहले, हमें अपने ऐप्लिकेशन को बनाना और डिप्लॉय करना होगा. इससे हमें परफ़ॉर्मेंस का एक बेसलाइन डेटा मिलेगा. बाद में, हम इसकी तुलना नेटिव वर्शन से कर सकते हैं.
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. कोड में बदलाव
प्रोजेक्ट खोलने के बाद, हम इसमें तुरंत एक साइन ऑफ़ लाइफ़ जोड़ेंगे. साथ ही, इसे चलाने के बाद Spring Native की परफ़ॉर्मेंस दिखाएंगे.
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 में ये एलिमेंट जोड़ने होंगे. इन्हें अपनी पसंद के एडिटर में जोड़ा जा सकता है.
हमारी pom फ़ाइल में, यहां दी गई रिपॉज़िटरी और pluginRepositories सेक्शन जोड़ें:
<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. डिपेंडेंसी जोड़ना
इसके बाद, स्प्रिंग-नेटिव डिपेंडेंसी जोड़ें. स्प्रिंग ऐप्लिकेशन को नेटिव इमेज के तौर पर चलाने के लिए, यह ज़रूरी है. ध्यान दें: अगर 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>
अब हम स्प्रिंग-बूट-मेवन-प्लगइन को अपडेट करेंगे, ताकि नेटिव इमेज की सुविधा चालू की जा सके. साथ ही, हम अपनी नेटिव इमेज बनाने के लिए, 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>
ध्यान दें कि Tiny Builder इमेज, कई विकल्पों में से सिर्फ़ एक विकल्प है. यह हमारे इस्तेमाल के उदाहरण के लिए एक अच्छा विकल्प है, क्योंकि इसमें बहुत कम अतिरिक्त लाइब्रेरी और यूटिलिटी हैं. इससे हमारे सिस्टम पर हमला होने की आशंका कम हो जाती है.
उदाहरण के लिए, अगर आपको ऐसा ऐप्लिकेशन बनाना है जिसे कुछ सामान्य C लाइब्रेरी ऐक्सेस करने की ज़रूरत है या आपको अब तक अपने ऐप्लिकेशन की ज़रूरी शर्तों के बारे में पक्का नहीं पता है, तो full-builder आपके लिए बेहतर विकल्प हो सकता है.
5. नेटिव ऐप्लिकेशन बनाना और उसे चलाना
यह सब सेट अप हो जाने के बाद, हम अपनी इमेज बना सकते हैं और अपने नेटिव, कंपाइल किए गए ऐप्लिकेशन को चला सकते हैं.
बिल्ड चलाने से पहले, इन बातों का ध्यान रखें:
- इसमें सामान्य बिल्ड की तुलना में ज़्यादा समय लगेगा (कुछ मिनट)

- इस बिल्ड प्रोसेस में बहुत ज़्यादा मेमोरी (कुछ गीगाबाइट) लग सकती है

- इस बिल्ड प्रोसेस के लिए, Docker daemon का ऐक्सेस होना ज़रूरी है
- इस उदाहरण में, हम प्रोसेस को मैन्युअल तरीके से पूरा कर रहे हैं. हालांकि, बिल्ड फ़ेज़ को इस तरह से भी कॉन्फ़िगर किया जा सकता है कि नेटिव बिल्ड प्रोफ़ाइल अपने-आप ट्रिगर हो जाए.
अपनी इमेज बनाने के लिए:
mvn spring-boot:build-image
इसके बाद, हम नेटिव ऐप्लिकेशन का इस्तेमाल करने के लिए तैयार हैं!
हमारे ऐप्लिकेशन को चलाने के लिए:
docker run --rm -p 8080:8080 demo:0.0.1-SNAPSHOT
इस समय, हम नेटिव ऐप्लिकेशन के फ़ायदे और नुकसान, दोनों के बारे में जान चुके हैं.
हमने कंपाइल करने के समय को थोड़ा बढ़ा दिया है और मेमोरी का इस्तेमाल भी थोड़ा ज़्यादा किया है. हालांकि, इसके बदले हमें एक ऐसा ऐप्लिकेशन मिला है जो बहुत तेज़ी से शुरू हो सकता है और काफ़ी कम मेमोरी का इस्तेमाल करता है. यह वर्कलोड पर निर्भर करता है.
अगर हम नेटिव इमेज के साइज़ की तुलना ओरिजनल इमेज से करने के लिए docker images demo चलाते हैं, तो हमें साइज़ में काफ़ी कमी दिखती है:

हमें यह भी ध्यान रखना चाहिए कि इस्तेमाल के ज़्यादा मुश्किल मामलों में, एओटी कंपाइलर को यह बताने के लिए कि आपका ऐप्लिकेशन रनटाइम में क्या करेगा, अतिरिक्त बदलावों की ज़रूरत होती है. इस वजह से, अनुमान के मुताबिक कुछ वर्कलोड (जैसे कि बैच जॉब) इसके लिए बहुत सही हो सकते हैं. वहीं, अन्य के लिए ज़्यादा मेहनत करनी पड़ सकती है.
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
इसके बाद, हम इसे Artifact Registry में भेजने के लिए docker push का इस्तेमाल कर सकते हैं:
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. खास जानकारी/सफ़ाई
Google Cloud पर Spring Native ऐप्लिकेशन बनाने और उसे डिप्लॉय करने के लिए बधाई!
हमें उम्मीद है कि इस ट्यूटोरियल से आपको Spring Native प्रोजेक्ट के बारे में ज़्यादा जानने में मदद मिली होगी. साथ ही, आने वाले समय में अगर आपको इसकी ज़रूरत पड़ती है, तो आपको इसके बारे में याद रहेगा.
ज़रूरी नहीं: सेवा को बंद करना और/या उससे जुड़ा डेटा मिटाना
आपने इस कोडलैब के लिए Google Cloud प्रोजेक्ट बनाया है या किसी मौजूदा प्रोजेक्ट का फिर से इस्तेमाल किया है, इस बात का ध्यान रखें कि हमने जिन संसाधनों का इस्तेमाल किया है उनसे कोई ज़रूरी शुल्क न लिया जाए.
हमारे बनाए गए Cloud Run की सेवाओं को मिटाया या बंद किया जा सकता है. इसके अलावा, हमारे होस्ट किए गए इमेज को मिटाया जा सकता है या पूरे प्रोजेक्ट को बंद किया जा सकता है.
8. अन्य संसाधन
फ़िलहाल, Spring Native प्रोजेक्ट एक नया और एक्सपेरिमेंटल प्रोजेक्ट है. हालांकि, शुरुआती उपभोक्ताओं के लिए पहले से ही कई अच्छे संसाधन उपलब्ध हैं. इनकी मदद से, वे समस्याओं को हल कर सकते हैं और इस प्रोजेक्ट में शामिल हो सकते हैं:
अन्य संसाधन
यहां कुछ ऑनलाइन संसाधन दिए गए हैं, जो इस ट्यूटोरियल के लिए काम के हो सकते हैं:
- नेटिव हिंट के बारे में ज़्यादा जानें
- GraalVM के बारे में ज़्यादा जानें
- शामिल होने का तरीका
- नेटिव इमेज बनाते समय मेमोरी खत्म होने की गड़बड़ी
- ऐप्लिकेशन शुरू नहीं हो सका
लाइसेंस
इस काम के लिए, Creative Commons एट्रिब्यूशन 2.0 जेनेरिक लाइसेंस के तहत लाइसेंस मिला है.