פריסת זיכרון בוליאנית ובוליאנית ב- JVM

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

במאמר מהיר זה, נראה מה טביעת הרגל של a בוליאני ערך ב- JVM בנסיבות שונות.

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

2. התקנה

כדי לבדוק את פריסת הזיכרון של אובייקטים ב- JVM, נשתמש בהרחבה ב- Java Object Layout (JOL). לכן, עלינו להוסיף את jol-core תלות:

 org.openjdk.jol jol-core 0.10 

3. מידות אובייקט

אם נבקש מ- JOL להדפיס את פרטי ה- VM במונחים של גדלי אובייקט:

System.out.println (VM.current (). פרטים ());

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

# הפעלת 64-סיביות HotSpot VM. # שימוש ב- oop דחוס עם משמרת של 3 סיביות. # שימוש בקלאס דחוס עם משמרת של 3 סיביות. # אובייקטים מיושרים 8 בתים. # גדלי שדה לפי סוג: 4, 1, 1, 2, 2, 4, 4, 8, 8 [בתים] # גדלי רכיבי מערך: 4, 1, 1, 2, 2, 4, 4, 8, 8 [בתים ]

בשורות הראשונות אנו יכולים לראות מידע כללי אודות ה- VM. לאחר מכן אנו למדים על גדלי האובייקטים:

  • הפניות Java צורכות 4 בתים, בוליאניs /בתיםהם בתים אחד, לְהַשְׁחִירs /קצרs הם 2 בתים, ints /לָצוּףs הם 4 בתים, ולבסוף, ארוךs /לְהַכפִּילs הם 8 בתים
  • סוגים אלו צורכים את אותה כמות זיכרון גם כאשר אנו משתמשים בהם כאלמנטים של מערך

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

3.1. אין הפניות דחוסות

גם אם נשבית את הפניות הדחוסות באמצעות -XX: -UseCompressedOops, הגודל הבוליאני לא ישתנה בכלל:

# גדלי שדה לפי סוג: 8, 1, 1, 2, 2, 4, 4, 8, 8 [בתים] # גדלי רכיבי מערך: 8, 1, 1, 2, 2, 4, 4, 8, 8 [בתים ]

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

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

3.2. קריעת מילים

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

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

לסיכום, נושאים להתייחסות וקריעת מילים הם הסיבות העיקריות לכך בוליאניs הם יותר מסיבית אחת בלבד.

4. מצביעי עצמים רגילים (OOP)

עכשיו שאנחנו יודעים בוליאניs הם 1 בתים, בואו ניקח בחשבון את המעמד הפשוט הזה:

class BooleanWrapper {ערך בוליאני פרטי; }

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

System.out.println (ClassLayout.parseClass (BooleanWrapper.class) .toPrintable ());

ואז JOL תדפיס את פריסת הזיכרון:

 גודל קיזוז סוג סוג תיאור ערך 0 12 (כותרת אובייקט) לא מתאים 12 1 בוליאני בוליארי Wrapper. ערך לא מתאים 13 3 (אובדן בגלל יישור האובייקט הבא) גודל מופע: 16 בתים הפסדי שטח: 0 בתים פנימיים + 3 בתים חיצוניים = 3 בתים בסך הכל

ה בוליאני עטיפה הפריסה מורכבת מ:

  • 12 בתים לכותרת, כולל שניים סימן מילים ואחת קלאס מִלָה. ה- HotSpot JVM משתמש ב- סימן מילה לאחסון מטא נתונים של GC, קוד hashcode וזהות נעילה. כמו כן, הוא משתמש ב- קלאס מילה לאחסון מטא נתונים בכיתה כגון בדיקות סוג זמן ריצה
  • בת אחד בפועל בוליאני ערך
  • 3 בתים של ריפוד למטרות יישור

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

לָכֵן, בוליאני שדות עשויים לצרוך יותר זיכרון בגלל יישור השדה שלהם.

4.1. יישור מותאם אישית

אם נשנה את ערך היישור ל 32 דרך -XX: ObjectAlignmentInBytes = 32, ואז אותה פריסת כיתה משתנה ל:

גודל קיזוז סוג תיאור ערך 0 12 (כותרת אובייקט) לא זמין 12 1 בוליאני בוליאני עוטף.ערך לא מתאים 13 19 (אובדן בגלל יישור האובייקט הבא) גודל מופע: 32 בתים הפסדי שטח: 0 בתים פנימיים + 19 בתים חיצוניים = 19 בתים בסך הכל

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

5. ערכי OOPs

בואו נראה איך ה- JVM פורש א בוליאני מערך בזיכרון:

ערך בוליאני [] = בוליאני חדש [3]; System.out.println (ClassLayout.parseInstance (value) .toPrintable ());

פעולה זו תדפיס את פריסת המופע כדלקמן:

קיזוז גודל סוג תיאור 0 4 (כותרת אובייקט) # מילת סימן 4 4 (כותרת עצם) # מילת סימן 8 4 (כותרת עצם) # מילה קלאסית 12 4 (כותרת אובייקט) # אורך מערך 16 3 בוליאני [Z. # [Z פירושו מערך בוליאני 19 5 (אובדן בגלל יישור האובייקט הבא)

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

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

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

6. מסקנה

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

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

כרגיל, כל הדוגמאות זמינות ב- GitHub.


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