קו התנהגות של אספן האשפה (מחזיר זיכרון)
מתכנת ה-Java אינו צריך לפקח על הקצאת זיכרון מכיוון שאוסף האשפה מנהל את הזיכרון באופן אוטומטי. אוסף הזבל מנוהל על ידי ה-Java Virtual Machine (JVM). אספן האשפה הוא תהליך בעל עדיפות נמוכה הפועל מדי פעם ומשחזר זיכרון המשמש חפצים שאינם נחוצים יותר. ל-JVMs שונים יש אלגוריתמים שונים לאיסוף אשפה. ישנם מספר אלגוריתמים בשימוש, לדוגמה: אלגוריתם ספירת הפניות או אלגוריתמי סימון וסגירה.
הפעלת אוסף האשפה בג'אווה
ה-JVM מפעיל בדרך כלל את אוסף האשפה כאשר הזיכרון הפנוי נמוך. אבל פעולת אספן האשפה לא מבטיחה שתמיד יהיה מספיק זיכרון פנוי. אם אין מספיק זיכרון גם לאחר השחזור, ה-JVM זורק חריג OutOfMemoryError. שימו לב שה-JVM חייב להפעיל את אוסף האשפה לפחות פעם אחת לפני לזרוק חריגה. אתה יכול לבקש מאוספן האשפה לפעול ב-Java, אך אינך יכול לכפות פעולה זו.
בקשה להפעיל את אוסף האשפה
כדי להגיש בקשה, אתה יכול להתקשר לאחת מהשיטות הבאות:
System.gc()
Runtime.getRuntime().gc()
התאמה להפעלת אספן אשפה
יש להשליך חפץ כאשר הוא אינו זמין עוד לזרם החי. חפץ עשוי להיות נתון לסילוק במקרים שונים:
- אם משתנה מסוג הפניה המתייחס לאובייקט מוגדר ל-"0", יש להיפטר מהאובייקט אם אין לו הפניות אחרות.
- אם נוצר משתנה מסוג הפניה המתייחס לאובייקט כדי להתייחס לאובייקט אחר, יש להיפטר מהאובייקט אם אין לו הפניות אחרות.
- אובייקטים שנוצרו באופן מקומי בשיטה נמחקים כאשר השיטה יוצאת, אלא אם הם מיוצאים מאותה שיטה (כלומר, מוחזרים או נזרקים כחריג).
- אובייקטים המתייחסים זה לזה עשויים להיות נתונים לסילוק אם אף אחד מהם אינו זמין לשרשור החי.
בואו נסתכל על דוגמה:
public class TestGC
{
public static void main(String [] args)
{
Object o1 = new Integer(3);
Object o2 = new String("Tutorial");
o1 = o2;
o2 = null;
}
}
בדוגמה זו
Integer
, ניתן להשליך את האובייקט (המספר השלם) שאליו הפנה מצביע o1 לאחר שורה 3 מכיוון ש-o1 מתייחס כעת לאובייקט
String
(מחרוזת). למרות ש-o2 נוצר כדי להתייחס ל-null, האובייקט
String
(מחרוזת) אינו ניתן למיחזור מכיוון ש-o1 מתייחס אליו.
סיום
טכנולוגיית Java מאפשרת לך להשתמש בשיטה
finalize()
(סופית) לבצע את הניקוי הדרוש לפני שאוסף האשפה מחזיר אובייקט מהזיכרון. שיטה זו נקראת על חפץ על ידי אספן האשפה כאשר אספן האשפה קובע שאין עוד אזכורים לחפץ. זה מתואר במחלקה
Object
, כלומר זה עובר בירושה על ידי כל המחלקות. תת המחלקה עוקפת את השיטה
finalize()
כדי להשתחרר ממשאבי המערכת או לניקוי אחר:
protected void finalize() throws Throwable
אם יוצא חריג לא רשום על ידי השיטה
finalize()
, מתעלמים מהחריג והסיום של האובייקט הזה נפסק. השיטה
finalize()
תופעל פעם אחת בלבד במהלך חיי האובייקט. אפשר להשתמש בשיטה
finalize()
על כל חפץ כדי להגן עליו מפני השלכה. אבל במקרה זה, אספן האשפה אינו מופעל יותר
finalize()
עבור חפץ זה. השיטה
finalize()
תמיד תופעל פעם אחת לפני שהאובייקט יאסוף אשפה. עם זאת, יתכן שהשיטה
finalize()
לא תופעל עבור אובייקט נתון במשך כל משך קיומו, מכיוון שהוא עשוי לא להיות נתון לסילוק.
סיכום
בחלק זה, הסתכלנו על תהליך איסוף האשפה, שהוא טכניקת ניהול זיכרון בשפת Java. אי אפשר לכפות איסוף אשפה. למדנו על הדרכים השונות להפוך חפצים לזכאים למיחזור ולמדנו שהשיטה
finalize()
מופעלת לפני שהחפץ מוחזק על ידי אוסף האשפה.
תרגיל
שאלה: כמה חפצים יהיו נתונים לסילוק אחרי שורה 7?
public class TutorialGC
{
public static void main(String [] args)
{
Object a = new Integer(100);
Object b = new Long(100);
Object c = new String("100");
a = null;
a = c;
c = b;
b = a;
}
}
אפשרויות תשובה: א. 0 ב. 1 ג. 2 ד. 3 ה. לא ניתן להרכיב את הקוד
אפשרות נכונה: ב
הסבר: מבין שלושת האובייקטים שנוצרו בשורות 1, 2 ו-3,
Integer
יש להשליך רק את האובייקט ב- סוף שורה 7. הפניות משתנות, a, שהתייחסו במקור לאובייקט
Integer
, מפנה לאובייקט
String
בשורה 5. לפיכך,
Integer
יש להיפטר מהאובייקט לאחר שורה 5, מכיוון שאין משתנים המפנים אליו. משתנים
b
ומתייחסים
c
לחפצים
String
וחפצים
Long
בשורות 6 ו-7, כך שהם אינם ניתנים למיחזור.
GO TO FULL VERSION