סגנון החיים של קובץ Java

ברוך הבא לפרק נוסף של "מתחת למכסה המנוע". במאמר בחודש שעבר דנתי ב- Java Virtual Machine, או JVM, המחשב המופשט שעבורו נערכות כל תוכניות ה- Java. אם אינך מכיר את ה- JVM, כדאי לך לקרוא את המאמר של החודש שעבר לפני זה. במאמר זה אני מספק הצצה למבנה הבסיסי ולאורח החיים של קובץ ה- Java בכיתה.

נולד לנסוע

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

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

אתה זקוק לדפדפן המותאם ל- Java כדי להציג יישומון זה

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

מה בתיק כיתתי?

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

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

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

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

מספרי קסם וגרסה

ארבעת הבתים הראשונים של כל קובץ מחלקה הם תמיד 0xCAFEBABE. מספר קסם זה מקל על זיהוי קבצי Java, מכיוון שהסיכויים הם קלים שקבצים שאינם מהמחלקה יתחילו עם אותם ארבעה בתים ראשוניים. המספר נקרא קסם מכיוון שמעצבי פורמט הקבצים יכולים לשלוף אותו מכובע. הדרישה היחידה היא שהוא כבר לא נמצא בשימוש על ידי פורמט קובץ אחר שעשוי להיתקל בעולם האמיתי. לדברי פטריק נוגהטון, חבר מפתח בצוות ג'אווה המקורי, מספר הקסם נבחר "הרבה לפני שהשם ג'אווה הוצא אי פעם בהתייחס לשפה זו. חיפשנו משהו מהנה, ייחודי וקל לזכור. זה רק צירוף מקרים ש- OxCAFEBABE, התייחסות אלכסונית לבריסטות החמודות בקפה של פיט, הקדימה את השם Java. "

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

בריכה קבועה

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

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

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

בהמשך המאמר אתייחס לפעמים לאלמנט ה- n של מערך הבריכות הקבוע כ- constant_pool [n]. זה הגיוני במידה והמאגר הקבוע מאורגן כמו מערך, אך יש לזכור כי לאלמנטים אלה יש גדלים וסוגים שונים וכי לאלמנט הראשון יש אינדקס של אחד.

גישה לדגלים

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

הכיתה הזאת

שני הבתים הבאים, רכיב המחלקה הזה , מהווים אינדקס למערך הבריכות הקבוע. לקבוע המתייחס אליו מחלקה זו , constant_pool [this_class], יש שני חלקים, תג בת אחד ואינדקס שמות של שני בתים. התג יהיה שווה ל- CONSTANT_Class, ערך המציין שאלמנט זה מכיל מידע על מחלקה או ממשק. Constant_pool [name_index] הוא קבוע מחרוזת המכיל את שם המחלקה או הממשק.

המעמד הזה מרכיב מספק הצצה לאופן בבריכה קבוע משמש. המעמד הזה עצמו הוא רק אינדקס למאגר הקבוע. כאשר JVM מחפש את constant_pool [this_class], הוא מוצא אלמנט שמזהה את עצמו כ- CONSTANT_Class עם התג שלו. ה- JVM יודע שלאלמנטים CONSTANT_Class יש תמיד אינדקס של שני בתים למאגר הקבוע, שנקרא אינדקס שמות, בעקבות תג הבתים האחד שלהם. אז זה מחפש את constant_pool [name_index] כדי לקבל את המחרוזת המכילה את שם המחלקה או הממשק.

סופר קלאס

בעקבות רכיב מחלקה זה נמצא רכיב סופר קלאסי, אינדקס שני בתים נוסף למאגר הקבוע. Constant_pool [super_class] הוא אלמנט CONSTANT_Class שמצביע על שם מחלקת העל שממנה יורדת מחלקה זו.

ממשקים

רכיב הממשקים מתחיל בספירה של שני בתים של מספר הממשקים המיושמים על ידי המחלקה (או הממשק) שהוגדרה בקובץ. מיד לאחר מכן מופיע מערך המכיל אינדקס אחד למאגר הקבוע לכל ממשק המיושם על ידי המחלקה. כל ממשק מיוצג על ידי אלמנט CONSTANT_Class בבריכה הקבועה שמצביעה על שם הממשק.

שדות

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

השדות היחידים שמופיעים ברשימה הם אלה שהוכרזו על ידי המחלקה או הממשק שהוגדרו בקובץ; לא מופיעים ברשימה שדות שעוברים בירושה ממחלקות-על או ממשקי-על.

שיטות

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

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

תכונות

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

טעינה: סימולציה של קובץ כיתה המגיע ליעד JVM שלו

היישומון שלהלן מדמה JVM שטוען קובץ מחלקה. קובץ הכיתה הנטען בסימולציה נוצר על ידי מהדר javac שקיבל את קוד המקור הבא של Java:

Act Act {public static void doMathForever () {int i = 0; בעוד (נכון) {i + = 1; i * = 2; }}}

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

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

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

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

לחיצה שמחה.

אתה זקוק לדפדפן המותאם ל- Java כדי להציג יישומון זה.

לחץ כאן לקבלת קוד המקור של GettingLoaded. כדי להריץ יישומון זה לבד, תזדקק גם לשני הקבצים שיישומון זה מאחזר מהשרת, קובץ ASCII המכיל את הטקסט לכל שלב וקובץ Act.class עצמו. לחץ כאן לקוד המקור של יישומון האודיו Flying Class Files.

הערה: האותיות הקטנות: מאמר "The Java Class File File Lifestyle" מאמר Copyright (c) 1996 Bill Venners. כל הזכויות שמורות. יישומון "GettingLoaded" זכויות יוצרים (c) 1996 חברת התוכנה Artima. כל הזכויות שמורות.

: END_END הערה

ביל ונטרס הוא נשיא חברת התוכנה ארטימה. באמצעות ארטימה הוא עוסק בפיתוח וייעוץ תוכנה בהתאמה אישית.

למידע נוסף על נושא זה

  • מפרט המכונה הווירטואלית של Java, המילה הרשמית של Sun.

    //java.sun.com/1.0alpha3/doc/vmspec/vmspec_1.html

  • כשהוא יוצא, הספר The Java Virtual Machine Specification , //www.aw.com/cp/lindholm-yellin.html, מאת טים ​​לינדהולם ופרנק ילין (ISBN 0-201-63452-X), חלק מה- Java הסדרה, //www.aw.com/cp/javaseries.html), מאדיסון ווסלי, תהיה ככל הנראה משאב ה- JVM הטוב ביותר.
  • ניתן לאחזר מ- JavaSoft טיוטה לפרק 4 של מפרט המכונה הווירטואלית של Java , המתארת ​​את פורמט הקובץ הכיתתי ומאמת קוד הביצוע.

    //java.sun.com/java.sun.com/newdocs.html

סיפור זה, "אורח החיים של קובץ כיתת Java" פורסם במקור על ידי JavaWorld.