Årsaker og unngåelse av java.lang.VerifyError

1. Introduksjon

I denne opplæringen vil vi se på årsaken til java.lang.VerifyError feil og flere måter å unngå det på.

2. Årsak

De Java Virtual Machine (JVM) mistroer alt lastet bytecode som en kjernen i Java Security Model. I løpet av kjøretiden lastes JVM .klasse filer og prøver å koble dem sammen for å danne en kjørbar fil - men gyldigheten av disse er lastet inn .klasse filer er ukjent.

For å sikre at lastet .klasse filer ikke utgjør en trussel mot den endelige kjørbare filen, utfører JVM verifisering på .klasse filer. I tillegg sørger JVM for at binærfiler er velformede. For eksempel vil JVM bekrefte at klassene ikke subtypes endelig klasser.

I mange tilfeller mislykkes verifisering av gyldig, ikke-skadelig bytekode fordi en nyere versjon av Java har en strengere bekreftelsesprosess enn eldre versjoner. For eksempel kan JDK 13 ha lagt til et verifiseringstrinn som ikke ble håndhevet i JDK 7. Hvis vi kjører et program med JVM 13 og inkluderer avhengigheter kompilert med en eldre versjon av Java Compiler (javac), kan JVM vurdere utdaterte avhengigheter for å være ugyldige.

Dermed når du kobler eldre .klasse filer med en nyere JVM, JVM kan kaste a java.lang.VerifyError ligner på følgende:

java.lang.VerifyError: Forventer en stackmap-ramme ved grenmål X Unntaksdetaljer: Plassering: com / eksempel / baeldung.Foo (Lcom / eksempel / baeldung / Bar: Baz;) Lcom / eksempel / baeldung / Foo; @ 1: infonull Årsak: Forventet stackmap-ramme på dette stedet. Bytecode: 0000000: 0001 0002 0003 0004 0005 0006 0007 0008 0000010: 0001 0002 0003 0004 0005 0006 0007 0008 ...

Det er to måter å løse dette problemet på:

  • Oppdater avhengigheter til versjoner samlet med en oppdatert javac
  • Deaktiver Java-bekreftelse

3. Produksjonsløsning

Den vanligste årsaken til en bekreftelsesfeil er å koble til binærfiler ved hjelp av en nyere JVM-versjon, samlet med en eldre versjon av javac. Dette er mer vanlig når avhengigheter har bykode generert av verktøy som Javassist, som kan ha generert utdatert bytekode hvis verktøyet er utdatert.

For å løse dette problemet, oppdater avhengigheter til enversjon bygget med en JDK-versjon som samsvarer med JDK-versjonen som ble brukt til å bygge applikasjonen. For eksempel, hvis vi bygger et program som bruker JDK 13, bør avhengighetene bygges ved hjelp av JDK 13.

For å finne en kompatibel versjon, inspiser Build-Jdk i JAR Manifest-filen av avhengighet for å sikre at den samsvarer med JDK-versjonen som ble brukt til å bygge applikasjonen.

4. Feilsøking og utviklingsløsning

Når vi feilsøker eller utvikler et program, kan vi deaktivere bekreftelse som en hurtigreparasjon.

Ikke bruk denne løsningen til produksjonskode.

Ved å deaktivere bekreftelse kan JVM koble skadelig eller feil kode til applikasjonene våre, noe som resulterer i sikkerhetskompromisser eller krasjer når de kjøres.

Vær også oppmerksom på at fra og med JDK 13 er denne løsningen avviklet, og vi bør ikke forvente at denne løsningen fungerer i fremtidige Java-utgivelser. Deaktivering av bekreftelse vil resultere i følgende advarsel:

Java HotSpot (TM) 64-biters VM-advarsel: Alternativer -Xverify: none og -noverify ble avviklet i JDK 13 og vil trolig bli fjernet i en fremtidig utgivelse.

Mekanismen for å deaktivere bekreftelse av bytecode varierer basert på hvordan vi kjører koden vår.

4.1. Kommandolinje

For å deaktivere bekreftelse på kommandolinjen, pass på noverify flagg til java kommando:

java -overvåke Foo.class

Noter det -opprettholde er en snarvei for-Kontroller: ingen og begge kan brukes om hverandre.

4.2. Maven

For å deaktivere bekreftelse i en Maven-bygging, send inn noverify flagg til ønsket plugin:

 com.example.baeldung eksempel-plugin -overvåke 

4.3. Gradle

For å deaktivere bekreftelse i en Gradle-bygging, send inn noverify flagg til ønsket oppgave:

someTask {// ... jvmArgs = jvmArgs << "-noverify"}

5. Konklusjon

I denne raske opplæringen lærte vi hvorfor JVM utfører bykodebekreftelse og hva som forårsaker java.lang.VerifyError feil. Vi undersøkte også to løsninger: En produksjon og en ikke-produksjon.

Når mulig, bruk de nyeste versjonene av avhengigheter i stedet for å deaktivere bekreftelse.


$config[zx-auto] not found$config[zx-overlay] not found