Class Data Sharing og optimalisering av JVM-oppstart
Få raskere oppstart i JVM-modus med CDS, lat initialisering og optimalisering av bean-instansiering.
Class Data Sharing og optimalisering av JVM-oppstart er en gratis leksjon i Komplett guide til Spring Boot 4 på CoddyKit. Dette er leksjon 3 av 4. Du kan lese valgfritt 3 leksjoner fra denne læringsstien gratis i sin helhet – deretter låser CoddyKit PRO opp alle leksjoner, samt praktisk øving med en innebygd kodeeditor og en AI-veileder som er tilgjengelig døgnet rundt. Den er en del av læringsløpet i Komplett guide til Spring Boot 4, og fremdriften din synkroniseres mellom nettet og CoddyKit-appen. Kurset i Komplett guide til Spring Boot 4 inneholder totalt 4 leksjoner.
Hvorfor JVM-oppstart fortsatt er viktig
GraalVM-native-images starter nesten umiddelbart, men de fleste team leverer fortsatt et vanlig JVM-bygg for det store flertallet av distribusjonene. JVM-en er enklere å feilsøke, støtter full refleksjon og fungerer med alle agenter og biblioteker uten ekstra tilpasning.
Den gode nyheten er at en Spring Boot 4-app i JVM-modus ikke trenger å starte tregt. Tre virkemidler har størst effekt:
- Class Data Sharing (CDS) — hopper over ny parsing av klassemetadata ved hver oppstart.
- Lazy initialization — oppretter bønner først når de brukes for første gang.
- Justering av bønneoppretting — unngår kostbart arbeid i konstruktører og ved oppfriskning.
Denne leksjonen går gjennom alle tre i JVM-modus, uten at et native-image kreves.
Hva Class Data Sharing faktisk gjør
Når JVM-en starter, laster den inn, analyserer og verifiserer hundrevis eller tusenvis av klasser. Class Data Sharing (CDS) skriver den analyserte klassegjengivelsen i minnet til en skrivebeskyttet arkivfil én gang, og minnekobler deretter dette arkivet ved hver påfølgende oppstart.
Fordelene er:
- Mindre arbeid med klasselasting og verifisering ved hver oppstart.
- Arkivet kan deles mellom flere JVM-prosesser (de samme fysiske minnesidene).
To varianter er relevante for Spring Boot 4:
- Dynamic CDS (AppCDS) — arkiverer applikasjonsklassene Deres, ikke bare JDK-klassene.
- Project Leyden / Ahead-of-Time cache — en videreutvikling som bygger på CDS i nyere JDK-er.
Spring Boot 4s innebygde CDS-støtte
Spring Boot har førsteklasses støtte for å generere et AppCDS-arkiv. De kjører appen én gang i en spesiell treningsmodus, den berører applikasjonskonteksten, avslutter og dumper et arkiv. Ved senere kjøringer peker De JVM-en mot dette arkivet.
Treningskjøringen bruker egenskapen nedenfor. Den oppfrisker konteksten og avslutter deretter uten å betjene trafikk:
-Dspring.context.exit=onRefreshstopper appen så snart konteksten er klar.- JVM-flaggene
-XX:ArchiveClassesAtExitfanger opp de innlastede klassene.
# 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.jarOptimalisering av layout med CDS-venlig JAR
En standard Spring Boot-fat-JAR legger avhengighets-JAR-er inni seg. CDS fungerer best når klassene ligger som vanlige filer på en sti JVM-en kan koble direkte til i minnet. Spring Boots tools-layout pakker ut appen til en katalog, slik at CDS kan indeksere den på en ryddig måte.
Pakk ut den kjørbare strukturen med den innebygde JAR-modusen, og kjør deretter fra den utpakkede layouten:
-Djarmode=tools extractskriver enapplication/-katalog med en flat classpath.- Kjøring fra den utpakkede formen gjør både trenings- og produksjonsoppstarter raskere og mer reproduserbare.
# 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.jarKontrollere at CDS er aktiv
Bekreft alltid at arkivet faktisk brukes; en skrivefeil i stien fører ubemerket tilbake til ingen CDS. Legg til logging av klasselasting for å se hvilke klasser som kommer fra det delte arkivet, og hvilke som kommer fra den vanlige classpathen.
Bruk det diagnostiske flagget ved en engangskontroll:
-Xlog:class+load:file=cds.logmerker hver klasse medsharednår den lastes fra arkivet.- Søk i loggen: Et velfungerende arkiv viser at hoveddelen av rammeverksklassene er merket
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 oppretting av bønner
Som standard oppretter Spring ivrig alle singleton-bønner under oppfriskningen av konteksten. Med mange bønner dominerer dette arbeidet oppstartstiden. Lazy initialization utsetter opprettelsen av hver bønne til den injiseres eller etterspørres for første gang.
Slå det på globalt med én egenskap:
spring.main.lazy-initialization=truegjør alle bønner lazy.- Avveining: Feil i en bønnes kobling oppdages når den brukes første gang, ikke ved oppstart, og den første forespørselen som berører en kald bønne, må betale opprettelseskostnaden.
Dette egner seg best for kortvarige CLI-oppgaver og rask oppstart i utvikling; vær forsiktig i tjenester som alltid kjører, der en treg første forespørsel er verre enn en litt tregere oppstart.
spring.main.lazy-initialization=trueSelektiv lazy-oppretting med @Lazy
Global lazy-oppretting er grovkornet. Ofte ønsker De at de fleste bønner skal opprettes ivrig, slik at feil oppdages ved oppstart, men at noen få tunge bønner skal opprettes lazy — for eksempel en klient som åpner en treg forbindelse, eller en hurtigbuffer som forhåndslaster et stort datasett.
Annoter bønnen eller injeksjonspunktet med @Lazy. Spring injiserer da en proxy og oppretter den virkelige bønnen ved det første kallet.
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);
}
}Hold bønnekonstruktører kostnadseffektive
Den største selvforskyldte oppstartsskaden er å utføre reelt arbeid i konstruktører eller @PostConstruct-metoder: åpne forbindelser, varme opp hurtigbuffere og kalle eksterne tjenester. Alt dette kjøres sekvensielt under oppfriskningen og blokkerer oppstarten.
Tommelfingerregler:
- Konstruktører skal bare lagre avhengigheter, aldri utføre I/O.
- Utsett kostbar oppvarming til en hendelse som utløses etter at konteksten er klar, eller kjør den asynkront.
- Lytt etter
ApplicationReadyEventfor oppvarming som ikke skal blokkere oppstarten av konteksten.
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();
}
}Bakgrunnsoppretting av bønner
Spring Boot kan opprette kvalifiserte bønner i et bakgrunnstrådpool mens hovedtråden fortsetter oppfriskningen. Dette parallelliserer uavhengige bønner som tar lang tid å opprette, og reduserer oppstartstiden i klokketid.
Definer en bootstrapExecutor-bønne; Spring bruker den til å opprette bønner som velger dette, i bakgrunnen. Bønner som ikke er avhengige av disse, fortsetter på hovedtråden.
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;
}
}Måle oppstart med Startup Actuator
Ikke gjett hvor tiden forsvinner — mål. Spring Boot registrerer en oppstartstidslinje for hvert trinn (oppretting av bønner, etterbehandling og autokonfigurasjon) når De oppgir en BufferingApplicationStartup.
Koble den inn i main(), og les deretter de bufrede hendelsene fra endepunktet /actuator/startup for å finne de tregeste trinnene. Sorter etter varighet, og ta først tak i de største tidstyvene.
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);
}
}Slik settes alt sammen: En oppskrift på optimalisert oppstart
En realistisk optimaliseringsrunde i JVM-modus for en Spring Boot 4-tjeneste kombinerer teknikkene i denne rekkefølgen:
- 1. Pakk ut JAR-en (
jarmode=tools extract), og generer et AppCDS-arkiv med en treningskjøring. - 2. Bruk
@Lazypå noen få genuint tunge bønner; la resten opprettes ivrig, slik at konfigurasjonsfeil oppdages raskt. - 3. Flytt all oppvarming og I/O ut av konstruktørene og inn i lyttere for
ApplicationReadyEvent. - 4. Legg til en
bootstrapExecutorhvis De har flere uavhengige, trege bønner. - 5. Bruk
BufferingApplicationStartupfor å bekrefte at hver endring ga effekt.
Startkommandoen peker deretter ganske enkelt på arkivet:
java -XX:SharedArchiveFile=app/app.jsa \
-Dspring.threads.virtual.enabled=true \
-jar app/myapp.jarHurtigsjekk: Velge riktig virkemiddel
Du har en Spring Boot 4-nettjeneste som alltid er i drift. Profilering viser at oppstartstiden i hovedsak brukes på å analysere og verifisere rammeverksklasser på nytt ved hver omstart, og at enkelte forespørsler treffer beans som aldri har blitt varmet opp. Du ønsker en raskere gjentakbar oppstart uten risiko for at den første brukerforespørselen blir merkbart treg.
Oppsummering
Spring Boot 4 i JVM-modus kan starte raskt uten å bygges som native. Viktigste punkter:
- CDS minnekartlegger et forhåndsbehandlet klassearkiv. Opprett det med en treningskjøring (
-XX:ArchiveClassesAtExit+spring.context.exit=onRefresh), og bruk det med-XX:SharedArchiveFile. Pakk ut jar-filen først for å få en CDS-vennlig layout. - Lazy init utsetter opprettelsen av beans: globalt via
spring.main.lazy-initialization, eller målrettet via@Lazy. Dette bytter bort fail-fast og latenstid for den første forespørselen mot raskere oppstart. - Justering av beans: Hold konstruktører enkle, flytt oppvarming til
ApplicationReadyEvent, og parallelliser uavhengige beans som tar lang tid, med enbootstrapExecutor. - Mål alt med
BufferingApplicationStartupog/actuator/startup— finjuster de tregeste trinnene, ikke antakelsene dine.
Lær deg Java med en AI-veileder – gratis
Skriv og kjør ekte kode i nettleseren, få umiddelbar hjelp fra en AI-veileder som er tilgjengelig døgnet rundt, og fortsett der du slapp – på nettet eller i appen.
- Kurs
- 21
- Leksjoner
- 84
Ofte stilte spørsmål
Er leksjonen «Class Data Sharing og optimalisering av JVM-oppstart» gratis?
Ja – du kan lese valgfritt 3 av leksjonene i læringsstien Komplett guide til Spring Boot 4, inkludert «Class Data Sharing og optimalisering av JVM-oppstart», gratis i sin helhet her på nettet. Deretter låser CoddyKit PRO opp alle leksjoner, samt interaktiv øving med en innebygd kodeeditor og en AI-veileder som er tilgjengelig døgnet rundt. Kurset i Komplett guide til Spring Boot 4 inneholder totalt 4 leksjoner.
Hva lærer jeg i «Class Data Sharing og optimalisering av JVM-oppstart»?
Få raskere oppstart i JVM-modus med CDS, lat initialisering og optimalisering av bean-instansiering. Du øver på Komplett guide til Spring Boot 4 med praktisk kode som du kjører direkte i nettleseren, mens en AI-veileder som er tilgjengelig døgnet rundt, svarer på spørsmålene dine mens du jobber deg gjennom leksjonen.
Trenger jeg erfaring for å begynne med Komplett guide til Spring Boot 4?
Ingen tidligere erfaring er nødvendig. Komplett guide til Spring Boot 4 på CoddyKit er lagt opp for både nybegynnere og viderekomne, så De kan begynne her eller helt fra start og lære i Deres eget tempo. Dette er leksjon 3 av 4.
Hvor lang tid tar leksjonen «Class Data Sharing og optimalisering av JVM-oppstart»?
De fleste CoddyKit-leksjoner tar omtrent 5–10 minutter. Hver leksjon er kort og interaktiv, slik at De gjør jevne fremskritt og kan fortsette akkurat der De slapp – både på nettet og i appen.
Kan jeg skrive og kjøre kode i denne Komplett guide til Spring Boot 4-leksjonen?
Ja. Alle Komplett guide til Spring Boot 4-leksjoner har en innebygd kodeeditor, slik at De kan skrive og kjøre ekte kode direkte i nettleseren og få umiddelbar tilbakemelding fra AI – uten lokal konfigurering.
Alle leksjonene i dette kurset
- AOT-behandling og den native byggeprosessen
- Runtime-hint for refleksjon og ressurser
- Class Data Sharing og optimalisering av JVM-oppstart
- Diagnostisering og løsning av kompatibilitetsproblemer i native builds