גורם והימנעות מ- java.lang.VerifyError

1. הקדמה

במדריך זה נבחן את הסיבה ל- java.lang.VerifyError שגיאות ודרכים רבות להימנע מכך.

2. סיבה

ה מכונת וירטואלית של ג'אווה (JVM) אינה אמונה על כל קוד ה- BYT הטעון כעקרון ליבה של מודל האבטחה של ג'אווה. בזמן ריצה ה- JVM יטען .מעמד קבצים ולנסות לקשר אותם יחד ליצירת הפעלה - אך תוקף אלה נטען .מעמד קבצים אינו ידוע.

כדי להבטיח שהטענת .מעמד קבצים אינם מהווים איום על ההפעלה הסופית, ה- JVM מבצע אימות ב- .מעמד קבצים. בנוסף, ה- JVM מבטיח שהבינאריות יהיו מעוצבות היטב. לדוגמה, ה- JVM יוודא שהמחלקות אינן תת-סוג סופי שיעורים.

במקרים רבים, האימות נכשל בקוד Byte חוקי ולא זדוני בגלל בגרסה חדשה יותר של Java יש תהליך אימות מחמיר מגרסאות ישנות יותר. לדוגמה, ייתכן ש- JDK 13 הוסיף שלב אימות שלא נאכף ב- JDK 7. לפיכך, אם אנו מריצים יישום עם JVM 13 ונכלול תלות שמורכבת עם גרסה ישנה יותר של Java Compiler (javac), ה- JVM עשוי לשקול את תלות מיושנת כדי להיות לא חוקית.

לפיכך, בעת קישור ישן יותר .מעמד קבצים עם JVM חדש יותר, ה- JVM עשוי לזרוק א java.lang.VerifyError דומה לדברים הבאים:

java.lang.VerifyError: צפייה למסגרת stackmap ביעד הענף X פרטי חריג: מיקום: com / example / baeldung.Foo (Lcom / example / baeldung / Bar: Baz;) Lcom / example / baeldung / Foo; @ 1: סיבה לא ידועה: מסגרת stackmap צפויה במיקום זה. קידוד: 0000000: 0001 0002 0003 0004 0005 0006 0007 0008 0000010: 0001 0002 0003 0004 0005 0006 0007 0008 ...

ישנן שתי דרכים לפתור בעיה זו:

  • עדכן תלות בגרסאות שהורכבו עם עדכון ג'אוואק
  • השבת אימות Java

3. פתרון ייצור

הגורם השכיח ביותר לשגיאת אימות הוא קישור בינאריות באמצעות גרסת JVM חדשה יותר שהורכבה עם גרסה ישנה יותר של ג'אוואק. זה נפוץ יותר כאשר לתלות נוצר קוד byt על ידי כלים כמו Javassist, אשר אולי יצר קוד byt מיושן אם הכלי מיושן.

כדי לפתור בעיה זו, עדכן תלות ל-גרסה שנבנתה באמצעות גרסת JDK התואמת את גרסת JDK המשמשת לבניית היישום. לדוגמא, אם אנו בונים אפליקציה באמצעות JDK 13, יש לבנות את התלות באמצעות JDK 13.

כדי למצוא גרסה תואמת, בדוק את Build-Jdk בקובץ JAR Manifest של התלות כדי להבטיח שהוא תואם את גרסת JDK המשמשת לבניית היישום.

4. פתרון איתור באגים ופיתוח

בעת ניפוי באגים או פיתוח של יישום, אנו יכולים להשבית את האימות כתיקון מהיר.

אל תשתמש בפתרון זה לקוד ייצור.

על ידי השבתת האימות, ה- JVM יכול לקשר קוד זדוני או פגום ליישומים שלנו, וכתוצאה מכך פגיעות אבטחה או קריסות בעת ביצועו.

כמו כן, שים לב שנכון ל- JDK 13 פתרון זה הוצא משימוש, ואין לצפות כי פתרון זה יעבוד במהדורות Java עתידיות. השבתת האימות תביא לאזהרה הבאה:

אזהרת VM Server Server של 64 סיביות של Java HotSpot (TM): אפשרויות -אמת: אף אחד ו- -noverify הוצאו משימוש ב- JDK 13 וככל הנראה יוסרו במהדורה עתידית.

מנגנון ההשבתה של אימות קוד byte משתנה בהתאם לאופן הפעלת הקוד שלנו.

4.1. שורת פיקוד

כדי להשבית את האימות בשורת הפקודה, העבירו את לא לאמת דגל ל ג'אווה פקודה:

java -nuverify Foo.class

ציין זאת -להאחיד הוא קיצור דרך עבור-אמת: אין וניתן להשתמש בשניהם לסירוגין.

4.2. Maven

כדי להשבית את האימות בבניית Maven, העבירו את לא לאמת דגל לכל תוסף רצוי:

 com.example.baeldung example-plugin -noverify 

4.3. Gradle

כדי להשבית את האימות בבניית Gradle, העבירו את לא לאמת דגל לכל משימה רצויה:

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

5. מסקנה

במדריך מהיר זה למדנו מדוע ה- JVM מבצע אימות קוד-קוד ומה גורם ל- java.lang.VerifyError שְׁגִיאָה. בדקנו גם שני פתרונות: ייצור אחד ולא ייצור.

כשמתאפשר, השתמש בגרסאות האחרונות של תלות במקום להשבית את האימות.


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