איתור באגים מרחוק ביישומי Java

1. סקירה כללית

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

במדריך זה נגלה כיצד לעשות זאת באמצעות הכלים של JDK.

2. היישום

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

מחלקה ציבורית OurApplication {private static String staticString = "מחרוזת סטטית"; מופע פרטי מחרוזת מחרוזת; ראשי סטטי ציבורי ריק (מחרוזת [] טוען) {עבור (int i = 0; i <1_000_000_000; i ++) {אפליקציית OurApplication = חדשה OurApplication (i); System.out.println (app.instanceString); }} OurApplication (int index) ציבורי {this.instanceString = buildInstanceString (אינדקס); } public String buildInstanceString (int מספר) {return number + ". String String!"; }} 

3. JDWP: פרוטוקול Java Debug Wire

ה פרוטוקול Wire Debug Wireהוא פרוטוקול המשמש בג'אווה לתקשורת בין ניפוי איתור באגים. ניפוי הבאגים הוא היישום שמבצע ניפוי באגים ואילו הבאגים הוא יישום או תהליך שמתחבר ליישום שמבוצע ניפוי באגים.

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

3.1. אפשרויות JDWP

נשתמש ב- JDWP בטיעוני שורת הפקודה JVM בעת הפעלת יישום הבאגים.

קריאתו דורשת רשימת אפשרויות:

  • תַחְבּוּרָה היא האפשרות היחידה הנדרשת לחלוטין. הוא מגדיר באיזה מנגנון תחבורה להשתמש. dt_shmem עובד רק ב- Windows ואם שני התהליכים פועלים על אותה מכונה בזמן dt_socket תואם את כל הפלטפורמות ומאפשר לרוץ לתהליכים במכונות שונות
  • שרת אינה אפשרות חובה. דגל זה, כאשר הוא פועל, מגדיר את האופן בו הוא מתחבר לבאגים. זה חושף את התהליך דרך הכתובת המוגדרת ב- כתובת אוֹפְּצִיָה. אחרת, JDWP חושף ברירת מחדל
  • לְהַשְׁעוֹת מגדיר אם ה- JVM צריך להשעות ולהמתין לצירוף באגים או לא
  • כתובת זוהי האפשרות המכילה את הכתובת, בדרך כלל יציאה, שנחשפת על ידי ניפוי הבאג. היא יכולה גם לייצג כתובת שתורגמה כמחרוזת תווים (כמו javadebug אם אנו משתמשים שרת = y מבלי לספק כתובת ב- Windows)

3.2. הפעל את הפקודה

נתחיל בהשקת היישום המרוחק. אנו נספק את כל האפשרויות המפורטות קודם:

java -agentlib: jdwp = transport = dt_socket, שרת = y, השעה = n, כתובת = 8000 היישום שלנו 

עד Java 5, טיעון JVM runjdwp היה צריך להשתמש ביחד עם האפשרות האחרת לנפות:

java -Xdebug -Xrunjdwp: transport = dt_socket, שרת = y, השעה = n, כתובת = 8000

דרך שימוש זו ב- JDWP עדיין נתמכת אך תיפטר במהדורות עתידיות. אנו מעדיפים להשתמש בסימון החדש יותר במידת האפשר.

3.3. מאז Java 9

לבסוף, אחת מהאפשרויות של JDWP השתנתה עם שחרור גרסה 9 של Java. זהו שינוי די קל שכן הוא נוגע רק לאפשרות אחת אך ישפיע אם ננסה לפתור באגים ביישום מרוחק.

שינוי זה משפיע על הדרך כתובת מתנהג ליישומים מרוחקים. הסימון הישן יותר כתובת = 8000 חל רק על מארח מקומי. כדי להשיג את ההתנהגות הישנה, ​​נשתמש בכוכבית עם נקודתיים כקידומת לכתובת (למשל כתובת = *: 8000).

על פי התיעוד, הדבר אינו מאובטח ומומלץ לציין את כתובת ה- IP של הבאגים במידת האפשר:

java -agentlib: jdwp = transport = dt_socket, שרת = y, השעה = n, כתובת = 127.0.0.1: 8000

4. JDB: Debugger Java

JDB, Debugger Java, הוא כלי הכלול ב- JDK שנוצר כדי לספק לקוח ניפוי באגים משורת הפקודה.

כדי להפעיל את JDB, נשתמש ב- לְצַרֵף מצב. מצב זה מצרף את JDB ל- JVM פועל. קיימים מצבי ריצה אחרים, כגון להקשיב אוֹ לָרוּץ אך הם נוחים בעיקר בעת ניפוי באגים ביישום הפועל באופן מקומי:

jdb -צרף 127.0.0.1:8000> אתחול jdb ... 

4.1. נקודות מעבר

בואו נמשיך לשים כמה נקודות עצירה ביישום המוצג בסעיף 1.

נקבע נקודת הפסקה על הבנאי:

> עצור ביישום שלנו. 

נגדיר אחת נוספת בשיטה הסטטית רָאשִׁי, באמצעות השם המלא של ה- חוּט מעמד:

> עצור ב- OurApplication.main (java.lang.String []) 

לבסוף, נגדיר את האחרונה בשיטת המופע buildInstanceString:

> עצור ב- OurApplication.buildInstanceString (int) 

כעת עלינו להבחין ביישום השרת נעצר ובדפוס הבא מודפס במסוף הבאגים שלנו:

> להיט נקודת עצירה: "thread = main", OurApplication. (), Line = 11 bci = 0 

בואו כעת נוסיף נקודת שבירה בשורה ספציפית, זו שבה המשתנה app.instanceString מודפס:

> עצור ביישום שלנו: 7 

אנו מבחינים בכך בְּ- משמש לאחר תפסיק במקום ב כאשר נקודת השבר מוגדרת בשורה ספציפית.

4.2. נווט והערך

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

עלינו לראות את הדברים הבאים מודפסים במסוף:

> נקודת פריצה: "thread = main", OurApplication.main (), line = 7 bci = 17 

כזכור, עצרנו בקו המכיל את פיסת הקוד הבאה:

System.out.println (app.instanceString); 

עצירה בקו זה יכולה הייתה להיעשות גם על ידי עצירה ב רָאשִׁי שיטה והקלדה שלב פעמיים. שלב מבצע את שורת הקוד הנוכחית ועוצר את הבאגים ישירות בשורה הבאה.

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

בוא נדפיס staticField לקונסולה:

> eval OurApplication.staticString OurApplication.staticString = "מחרוזת סטטית" 

שמנו במפורש את שם הכיתה לפני השדה הסטטי.

בואו כעת נדפיס את שדה המופע של אפליקציה:

> eval app.instanceString app.instanceString = "68741. מחרוזת מופע!" 

לאחר מכן, בואו נראה את המשתנה אני:

> הדפס i i = 68741 

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

אנו נעריך מופע חדש של היישום שלנו שעבורו העברנו מספר שלם כפרמטר קונסטרוקטור:

> הדפס OurApplication חדש (10) .instanceString OurApplication חדש (10) .instanceString = "10. מחרוזת מופע!" 

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

המזהה זהה לזה לזה ששימש קודם לכן עם הפקודה תפסיק:

> נקה את היישום שלנו: 7 הוסר: נקודת השבר היישום שלנו: 7 

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

> נקה נקודות עצירה: נקודת הפסקה היישום שלנו. נקודת הפסקה OurApplication.buildInstanceString (int) נקודת הפסקה OurApplication.main (java.lang.String []) 

5. מסקנה

אני: במאמר מהיר זה גילינו כיצד להשתמש ב- JDWP יחד עם JDB, שני כלי ה- JDK.

מידע נוסף על הכלים ניתן למצוא כמובן בהתייחסויות שלהם: JDWP ו- JDB - כדי להעמיק בנושאי הכלים.