Opgrader en kritisk Java 8-applikation i etaper: kortlæg alle afhængigheder, gå først til Java 11 og derefter til hver efterfølgende LTS-version (long-term support), og lad tests og belastningstests afgøre, hvornår hvert skridt er sikkert. Det meste af arbejdet ligger i biblioteker, byggeværktøjer og kode, der rører JDK'ens interne dele, ikke i din forretningslogik.
Hvis du bliver på Java 8, indsnævres dine muligheder år for år
En Java 8-applikation kan blive ved med at køre i årevis, og det er netop fælden. Sikkerhedsrettelser afhænger i stigende grad af en betalt supportaftale eller en distribution, der stadig tilbagefører dem, og de store biblioteker er gået videre. Spring Boot 3 kræver for eksempel mindst Java 17, så når du bliver på Java 8, fryser du også dine frameworkversioner.
Nyere JVM'er kører også den samme kode bedre. G1 har været standard-garbage collector siden Java 9, collectorer med korte pauser som ZGC er klar til produktion, og compact strings mindsker hukommelsesforbruget ved teksttunge workloads. Udviklere forventer også moderne sprogfunktioner som records, text blocks og switch expressions, hvilket gør det sværere at bemande en Java 8-kodebase.
Start med en kortlægning af alt, applikationen afhænger af
Selve opgraderingen af JDK'en er sjældent den svære del. Det svære er den lange hale af biblioteker, plugins og agenter, der blev skrevet til Java 8 og aldrig opdateret. Lav en komplet liste, før du ændrer noget, og notér versionen af hvert element.
- JDK-leverandør og -version i hvert miljø, fra udviklernes bærbare til produktion.
- Direkte og transitive afhængigheder, eksporteret fra Mavens afhængighedstræ eller Gradles rapport over afhængigheder.
- Build-plugins, kodegeneratorer og annotationsprocessorer som Lombok.
- Applikationsserveren eller servlet-containeren, hvis applikationen kører i en sådan.
- Java-agenter til overvågning, profilering eller sikkerhed, som griber dybt ind i JVM'en.
- Kode, der bruger interne JDK-API'er, fundet med værktøjet jdeps og dets jdk-internals-indstilling.
- JVM-flag, indstillinger for garbage collection og alle scripts, der parser outputtet fra java -version.
Gå trinvis gennem LTS-versionerne i stedet for at springe
Gå fra Java 8 til 11, derefter til 17 og så til 21 eller 25. Hvert spring har sine egne fjernelser og ændringer i adfærd, og ét stort spring blander dem alle sammen til én fejl, du ikke kan diagnosticere. Når du retter ét lag ad gangen, bliver hvert skridt lille nok til at blive gennemgået og rullet tilbage.
Opgrader bibliotekerne, mens du stadig er på Java 8, hvor det er muligt, for mange nyere versioner understøtter både gamle og nye JDK'er. Kør derefter det eksisterende build på den nye JVM, før du ændrer kompileringsmålet. Det adskiller runtime-problemer fra compilerproblemer, og compilerflaget release holder bytecode-målet eksplicit.
Gør testsuiten til porten for hvert skridt
Tests er dit eneste objektive signal om, at den opgraderede applikation stadig opfører sig på samme måde. Hvis kritiske forløb har lav dækning, så skriv først karakteriseringstests: tests, der indfanger, hvad systemet gør i dag, inklusive dets mærkelige kanttilfælde, uden at vurdere, om adfærden er rigtig.
Tilføj integrationstests, der kører mod en rigtig database og rigtige message brokers, fordi mange fejl ved opgraderinger først viser sig ved de grænseflader. For systemer med mange beregninger kan du afspille de samme input gennem den gamle og den nye version og sammenligne output felt for felt. Vær opmærksom på datoer, tal og tekst: Java 9 skiftede som standard til CLDR-lokaliseringsdata, og Java 18 gjorde UTF-8 til standardtegnsæt, og begge dele kan ændre formatering eller parsing i det stille.
Kend de faldgruber, der ødelægger Java 8-kode
De fleste fejl falder i nogle få kendte kategorier. Søg efter hver af dem før opgraderingen i stedet for at opdage dem i produktion.
- Fjernede Java EE- og CORBA-moduler: Java 11 fjernede JAXB, JAX-WS, JavaBeans Activation og common annotations fra JDK'en, så de skal tilføjes igen som eksplicitte afhængigheder.
- Stærk indkapsling af JDK'ens interne dele: ulovlig reflektiv adgang gav advarsler fra Java 9, afvises som standard siden Java 16 og kan ikke slås globalt til igen siden Java 17. Løs det ved at opgradere biblioteket; brug kun add-opens som en dokumenteret, midlertidig undtagelse.
- Forældede bytecode-værktøjer: ældre versioner af Lombok, Mockito, Byte Buddy, ASM og build-plugins fejler på nyere versioner af class-filformatet.
- Fjernede funktioner: JavaScript-motoren Nashorn blev fjernet i Java 15, og Security Manager blev udfaset i Java 17 og permanent deaktiveret i Java 24.
- Fjernede JVM-flag: CMS-garbage collectoren blev fjernet i Java 14, og en JVM, der startes med fjernede indstillinger, kan nægte at starte.
Bevis ydeevnen under realistisk belastning, ikke på en bærbar
En ny JDK ændrer garbage collectoren, JIT-compileren og hukommelseslayoutet, så ydeevnen kan bevæge sig i begge retninger. Kør en belastningstest, der genskaber trafikprofilen fra produktion, på samme hardware eller instanstype, før og efter hvert skridt. Sammenlign latenspercentiler, gennemstrømning, hukommelse og pauser i garbage collection, og lad JIT'en varme op, før du måler.
Vores udviklere ledede gennem Sopra Steria en migrering fra Java 8 til 16 af en kritisk applikation til dagshandel med gas for en national handelsdesk for gas. På det system skulle beregningerne af kapacitet og energiflow forblive korrekte og hurtige under højfrekvent belastning, så opgraderingen gik hånd i hånd med optimering af disse beregninger og blev valideret under belastning i stedet for at blive taget for givet.
Rul gradvist ud, og bevar en vej tilbage
Send først den opgraderede runtime ud til én instans eller en lille andel af trafikken, og hold øje med fejlrater, latens og garbage collection i forhold til udgangspunktet på Java 8. Hold det forrige build klar til udrulning, indtil den nye version har kørt gennem normale forretningscyklusser, inklusive månedsafslutning eller spidsbelastningsperioder.
Fjern først derefter Java 8-artefakterne, og begynd at bruge nye sprogfunktioner. Hvis du vil have hjælp til at planlægge eller gennemføre en opgradering som denne, bemander SDK Enterprises den med interne udviklere og udvalgte specialister under én kontrakt, hvor vi bærer ansvaret.
Det vigtigste
- Indsatsen i en Java 8-opgradering ligger mest i afhængigheder, byggeværktøjer og brug af JDK'ens interne dele, ikke i forretningslogikken.
- Gå gennem LTS-versionerne én ad gangen, så hver fejl har én årsag, der kan findes.
- Karakteriserings- og integrationstests er porten for hvert skridt, især omkring datoer, tal og tekstkodning.
- Validér ydeevnen under en produktionslignende belastning, fordi ændringer i garbage collection og JIT kan flytte resultaterne i begge retninger.
- Rul først ud til en lille andel af trafikken, og hold Java 8-buildet klar til udrulning, indtil den nye runtime har bevist sit værd.
FAQ
Kan jeg opgradere direkte fra Java 8 til Java 21?
Det kan du, men du arver alle ændringer fra Java 9 til 21 på én gang, hvilket gør fejl svære at spore. At gå trinvis via 11 og 17 koster lidt mere byggetid og sparer meget fejlsøgning på et kritisk system.
Hvor lang tid tager en opgradering fra Java 8?
Det afhænger af antallet af afhængigheder, hvor mange af dem der bruger JDK'ens interne dele, testdækningen, og hvor meget belastningstest systemet kræver. En kortlægning og en prøvekørsel på den nye JVM giver dig tidligt et realistisk estimat, før du forpligter dig til en tidsplan.
Skal jeg skrive koden om for at bruge nye Java-funktioner?
Nej. Java har stærk bagudkompatibilitet for kode, der holder sig til standard-API'er, som ikke er udfasede. Tag records, text blocks og andre funktioner i brug gradvist, når den opgraderede runtime er stabil i produktion.