مشاركة بيانات الفئات وضبط بدء تشغيل JVM
سرّع بدء التشغيل في وضع JVM باستخدام CDS والتهيئة الكسولة وضبط إنشاء الحبوب
مشاركة بيانات الفئات وضبط بدء تشغيل JVM درس مجاني في Spring Boot 4 Complete Guide على CoddyKit. هذا هو الدرس 3 من أصل 4. يمكنك قراءة الدرس كاملاً أدناه مجاناً — ثم تمرن عليه مباشرة في المتصفح باستخدام محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7. هذا الدرس جزء من مسار التعلم في Spring Boot 4 Complete Guide، وتقدمك يتزامن عبر الويب وتطبيق CoddyKit. تتضمن دورة Spring Boot 4 Complete Guide 4 دروس في المجموع.
بعض أجزاء هذا الدرس لم تُترجم بعد وتظهر باللغة الإنجليزية.
Why JVM Startup Still Matters
GraalVM native images give near-instant startup, but most teams still ship a regular JVM build for the vast majority of deployments. The JVM is easier to debug, supports full reflection, and works with every agent and library out of the box.
The good news: a JVM-mode Spring Boot 4 app does not have to be slow to start. Three levers move the needle the most:
- Class Data Sharing (CDS) — skip re-parsing class metadata on every boot.
- Lazy initialization — create beans only when first used.
- Bean instantiation tuning — avoid expensive work in constructors and at refresh time.
This lesson walks through all three, in JVM mode, no native image required.
What Class Data Sharing Actually Does
When the JVM starts, it loads, parses, and verifies hundreds or thousands of classes. Class Data Sharing (CDS) writes the parsed in-memory class representation into a read-only archive file once, then memory-maps that archive on every subsequent start.
The payoff:
- Less class loading and verification work per boot.
- The archive can be shared across multiple JVM processes (same physical memory pages).
Two flavors matter for Spring Boot 4:
- Dynamic CDS (AppCDS) — archive your application classes, not just the JDK ones.
- Project Leyden / Ahead-of-Time cache — an evolution layered on CDS in newer JDKs.
Spring Boot 4's Built-in CDS Support
Spring Boot has first-class support for generating an AppCDS archive. You run the app once in a special training mode, it touches the application context, exits, and dumps an archive. Subsequent runs point the JVM at that archive.
The training run uses the special property below. It performs context refresh and then shuts down without serving traffic:
-Dspring.context.exit=onRefreshstops the app right after the context is ready.- The JVM flags
-XX:ArchiveClassesAtExitcapture the loaded classes.
# Step 1: training run - refresh context, then exit, dumping the archive
java -XX:ArchiveClassesAtExit=app.jsa \
-Dspring.context.exit=onRefresh \
-jar target/myapp.jar
# Step 2: every production start reuses the archive
java -XX:SharedArchiveFile=app.jsa \
-jar target/myapp.jarLayout Optimization with the CDS-Friendly Jar
A standard Spring Boot fat jar nests dependency jars inside it. CDS works best when classes live as plain files on a path the JVM can map directly. Spring Boot's tools layout extracts the app into a directory so CDS can index it cleanly.
Extract the runnable structure with the built-in jar mode, then run from the exploded layout:
-Djarmode=tools extractwrites anapplication/directory with a flat classpath.- Running from the exploded form makes both training and production starts faster and more reproducible.
# Explode the jar into a CDS-friendly directory structure
java -Djarmode=tools -jar target/myapp.jar extract --destination app
# Train against the exploded app
java -XX:ArchiveClassesAtExit=app/app.jsa \
-Dspring.context.exit=onRefresh \
-jar app/myapp.jar
# Production start
java -XX:SharedArchiveFile=app/app.jsa -jar app/myapp.jarVerifying CDS Is Active
Always confirm the archive is actually being used; a typo in the path silently falls back to no CDS. Add class-load logging to see which classes come from the shared archive versus the regular classpath.
Use the diagnostic flag during a one-off check:
-Xlog:class+load:file=cds.logtags each class withsharedwhen it loads from the archive.- Grep the log: a healthy archive shows the bulk of framework classes marked
shared.
# Run with class-load logging and inspect the source of each class
java -XX:SharedArchiveFile=app/app.jsa \
-Xlog:class+load:file=cds.log \
-jar app/myapp.jar
# Count how many classes were served from the shared archive
grep -c 'source: shared objects file' cds.logLazy Bean Initialization
By default Spring eagerly instantiates every singleton bean during context refresh. With many beans, that work dominates startup. Lazy initialization defers each bean's creation until it is first injected or requested.
Turn it on globally with one property:
spring.main.lazy-initialization=truemakes all beans lazy.- Trade-off: errors in a bean's wiring surface at first use instead of at boot, and the first request that touches a cold bean pays its construction cost.
Prefer it for short-lived CLI tasks and dev startup; be cautious in always-on services where a slow first request is worse than a slightly slower boot.
spring.main.lazy-initialization=trueSelective Laziness with @Lazy
Global laziness is blunt. Often you want most beans eager (so failures are caught at boot) but a few heavy beans lazy — a client that opens a slow connection, or a cache that pre-loads a large dataset.
Annotate the bean or the injection point with @Lazy. Spring then injects a proxy and instantiates the real bean on first call.
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Lazy;
@Configuration
public class ReportingConfig {
// Heavy bean: only built when something actually needs it
@Bean
@Lazy
public ReportGenerator reportGenerator(DataWarehouse warehouse) {
return new ReportGenerator(warehouse);
}
}Keep Bean Constructors Cheap
The single biggest self-inflicted startup wound is doing real work in constructors or @PostConstruct methods: opening connections, warming caches, calling remote services. All of it runs during refresh, serially, blocking startup.
Rules of thumb:
- Constructors should only store collaborators, never perform I/O.
- Defer expensive warm-up to an event that fires after the context is ready, or run it asynchronously.
- Listen for
ApplicationReadyEventfor warm-up that should not block the context from coming up.
import org.springframework.boot.context.event.ApplicationReadyEvent;
import org.springframework.context.event.EventListener;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Component;
@Component
public class CacheWarmer {
private final ProductCache cache;
public CacheWarmer(ProductCache cache) {
// cheap: just hold the dependency
this.cache = cache;
}
// Runs after startup, off the critical path
@Async
@EventListener(ApplicationReadyEvent.class)
public void warmUp() {
cache.preload();
}
}Background Bean Instantiation
Spring Boot can instantiate eligible beans on a background thread pool while the main thread continues refreshing. This parallelizes independent, slow-to-construct beans and shrinks wall-clock startup time.
Define a bootstrapExecutor bean; Spring uses it to construct beans that opt in, in the background. Beans with no dependency on those still proceed on the main thread.
import java.util.concurrent.Executor;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
@Configuration
public class BootstrapConfig {
// Spring detects a bean named 'bootstrapExecutor' for background init
@Bean
public Executor bootstrapExecutor() {
ThreadPoolTaskExecutor exec = new ThreadPoolTaskExecutor();
exec.setCorePoolSize(4);
exec.setThreadNamePrefix("bg-init-");
exec.initialize();
return exec;
}
}Measuring Startup with the Startup Actuator
Don't guess where the time goes — measure. Spring Boot records a startup timeline of every step (bean instantiation, post-processing, auto-configuration) when you supply a BufferingApplicationStartup.
Wire it in main(), then read the buffered events from the /actuator/startup endpoint to find the slowest steps. Sort by duration and attack the top offenders first.
import org.springframework.boot.SpringApplication;
import org.springframework.boot.autoconfigure.SpringBootApplication;
import org.springframework.boot.context.metrics.buffering.BufferingApplicationStartup;
@SpringBootApplication
public class ShopApplication {
public static void main(String[] args) {
SpringApplication app = new SpringApplication(ShopApplication.class);
// capture up to 2048 startup steps for /actuator/startup
app.setApplicationStartup(new BufferingApplicationStartup(2048));
app.run(args);
}
}Putting It Together: A Tuned Startup Recipe
A realistic JVM-mode tuning pass for a Spring Boot 4 service combines the techniques in order of impact:
- 1. Extract the jar (
jarmode=tools extract) and generate an AppCDS archive with a training run. - 2. Apply
@Lazyto a handful of genuinely heavy beans; keep the rest eager so config errors fail fast. - 3. Move all warm-up / I/O out of constructors into
ApplicationReadyEventlisteners. - 4. Add a
bootstrapExecutorif you have several independent slow beans. - 5. Use
BufferingApplicationStartupto confirm each change helped.
The launch command then simply points at the archive:
java -XX:SharedArchiveFile=app/app.jsa \
-Dspring.threads.virtual.enabled=true \
-jar app/myapp.jarQuick Check: Choosing the Right Lever
You have an always-on Spring Boot 4 web service. Profiling shows boot time is dominated by re-parsing and verifying framework classes on every restart, and a few requests hit beans that were never warmed. You want faster repeatable startup without risking that the first user request becomes noticeably slow.
Recap
JVM-mode Spring Boot 4 can start fast without going native. Key takeaways:
- CDS memory-maps a pre-parsed class archive; create it with a training run (
-XX:ArchiveClassesAtExit+spring.context.exit=onRefresh) and consume it with-XX:SharedArchiveFile. Extract the jar first for a CDS-friendly layout. - Lazy init defers bean creation: global via
spring.main.lazy-initialization, or surgical via@Lazy. It trades fail-fast and first-request latency for a quicker boot. - Bean tuning: keep constructors cheap, move warm-up to
ApplicationReadyEvent, and parallelize independent slow beans with abootstrapExecutor. - Measure everything with
BufferingApplicationStartupand/actuator/startup— tune the slowest steps, not your assumptions.
تعلم Java مع معلم ذكاء اصطناعي — مجانًا
اكتب وقم بتشغيل أكوادك الفعلية في المتصفح، واحصل على مساعدة فورية من معلم ذكاء اصطناعي متاح 24/7، واستمر من حيث توقفت على الويب أو في التطبيق.
- الدورات
- 21
- الدروس
- 84
الأسئلة الشائعة
هل درس «مشاركة بيانات الفئات وضبط بدء تشغيل JVM» مجاني؟
نعم — نص درس «مشاركة بيانات الفئات وضبط بدء تشغيل JVM» كامل متاح مجاناً هنا على الويب. لتمرينه بشكل تفاعلي (محرر أكواد مدمج ومدرس ذكاء اصطناعي متاح 24/7) وفتح باقي دورة Spring Boot 4 Complete Guide، انتقل إلى CoddyKit PRO. تتضمن دورة Spring Boot 4 Complete Guide 4 دروس في المجموع.
ماذا ستتعلم في «مشاركة بيانات الفئات وضبط بدء تشغيل JVM»؟
سرّع بدء التشغيل في وضع JVM باستخدام CDS والتهيئة الكسولة وضبط إنشاء الحبوب تتمرن على Spring Boot 4 Complete Guide مع أكواد عملية تشغلها مباشرة في المتصفح، ومدرس ذكاء اصطناعي متاح 24/7 يجيب على أسئلتك أثناء عملك.
هل أحتاج إلى خبرة سابقة لأبدأ Spring Boot 4 Complete Guide؟
لا تُشترط خبرة سابقة. Spring Boot 4 Complete Guide على CoddyKit منظم للمبتدئين حتى المتقدمين، لذا يمكنك البدء من هنا أو من البداية والتقدم بسرعتك الخاصة. هذا هو الدرس 3 من أصل 4.
كم من الوقت يستغرق درس «مشاركة بيانات الفئات وضبط بدء تشغيل JVM»؟
معظم دروس CoddyKit تستغرق حوالي 5–10 دقائق. كل منها موجز وتفاعلي، لذا تحرز تقدماً مستمراً وتستأنف من حيث توقفت عبر الويب والتطبيق.
هل يمكنني كتابة وتشغيل أكواد في درس Spring Boot 4 Complete Guide هذا؟
نعم. كل درس في Spring Boot 4 Complete Guide يتضمن محرر أكواد مدمج، لذا تكتب وتشغل أكواداً حقيقية مباشرة في متصفحك وتحصل على تعليقات فورية من الذكاء الاصطناعي — بدون إعداد محلي.
جميع الدروس في هذه الدورة
- معالجة AOT ومسار البناء الأصلي
- تلميحات وقت التشغيل للانعكاس والموارد
- مشاركة بيانات الفئات وضبط بدء تشغيل JVM
- تشخيص مشكلات التوافق الأصلي وإصلاحها