Logo

רד-בורד: ארכיון

ראשי > תיכנות > מחיקה מה-Garbage Collector בג’אווה

27/04/2012 15:37:29 Admin
בניתי תוכנית בג’אווה שמדמה זכרון מחשב.
התוכנית מקבלת מערך של 1000 סטרינגים כזכרון משני, ורשימה מקושרת כפולה (עם מצביעים לאיבר הקודם והאיבר הבא) עם קיבולת מקסימלית של 50 חוליות. ובעצם כל פעם שפונים לאיזשהו קובץ (לקריאה או כתיבה) מה שהתוכנית עושה זה בודקת אם הוא קיים בזכרון הראשי, אם לא- מעבירה אותו מהזכרון המשני לראשי, ואז עובדת עליו שם (ואם הוא כן שם אז כמובן קוראת אותו משם). ורק כשהוא יוצא מהזכרון הראשי חזרה למשני (כשהזכרון הראשי מתמלא ב50 חוליות חדשות והוא נבעט החוצה מחוסר מקום) הוא מתעדכן בראשי.

מעבר להסבר הכללי הזה, התוכנית עונה על כל התנאים שנדרשים במסמך הבא:
http://www.cs.bgu.ac.il/~ds122/wiki.files/Assignment2.pdf
שהעיקרי שבהם הוא שהפניה לקבצים בזכרון הראשי תעשה בגישה ישירה- זמן ריצה O(1).

השאלה שלי היא כזאת:
כשאני יוצר חוליה חדשה ברשימה המקושרת (=קובץ חדש בזכרון הראשי) אני עושה:
new Link()
ובעצם יוצר עכשיו ישות חדשה (מקווה שישות זו המילה הנכונה?).
לעומת זאת, כשאני רוצה למחוק את החולייה מהרשימה (=להוציא את הקובץ מהזכרון הראשי) מה שאני עושה זה מסיר את הפויינטר מהחוליה שלפניה ומפנה אותה (את החוליה שלפניה) לכלום (null).
למקרה שמה שאמרתי קצת מבלבל, זה הקוד:
: /*
* Remove value from the end of the LinkedList and return it
* @return the removed value
*/
public Page removeLast() {
if (isEmpty()) return null; // if the LinkedList is empty there is nothing to remove. return null
Link val=first;
while(val.next.next!=null) // move to the end of the LinkedList
val=val.next;
Page removeVal = val.next.data;
val.next = null; // remove the last value
return removeVal;
}//removeLast

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

עשיתי קצת חיפוש האם אפשר למחוק מהגרבג’ קולקטור והגעתי לדיון הבא:
Removing objects from Java Collections
הם טוענים שאין שום אפשרות למחוק קבצים מהגרבג’ קולקטור והוא מטפל בהכל לבד.
לא מצאתי תשובה יותר טובה, אבל עדיין היות ובאיזשהו מקום זה מקשה על המשימה שלי אני שואל את עצמי אם זאת בטוח התשובה. האם אתם יודעים משהו אחר, או יכולים לאשר את העובדה הזאת?

בנוסף הם מעלים שם בדיון הזה שאלה מאוד מעניינת- מה קורה אם משתמש יוצר סיסמה בג’אווה, ואז רוצה למחוק אותה? סיסמה זה הרי דבר חשוב והאידיאל הוא שהיא לא תזרק לאיזשהו גרבג’ קולקטור אלא תמחק לגמרי. הם הציעו שם לערוך את הסיסמה לפני הזריקה שלה לGC, אבל אז בתגובה לזה אמרו שעדיין הערך המקורי שלה לפני השינוי נשמר לGC.
לא יודע, משהו פה נשמע קצת לא הגיוני ולא חכם. או שאולי זה כן הגיוני וכן חכם? אשמח אם מישהו ידע לענות... ותודה מראש[ההודעה נערכה על-ידי Admin ב-27/04/2012 15:45:17]
29/04/2012 12:34:37 Admin
הנה כמה מהתשובות שקיבלתי מחברים מחוץ לפורום:
(1)
:היי שחף,
מה שאתה אומר זה בסדר. כשאתה יוצר יישות אתה בעצם,מצביע לנקודה בזיכרון ומתחיל כביכול לעקוב אחריה. וכשאתה מוחק אתה בעצם אומר עכשיו הנקודה הזאת לא מעניינת אותי אבל אין מחיקה פיזית,ואין,צורך למחוק את הgc או משהו כזה

(2)
:הי, שחף... הסתכלתי על זה,
לפי מה שאני מבינה מפריע לך שגם אחרי שאתה מוחק מישהו הוא נשאר בזכרון, וה-GC לא בא לאסוף אותו.
בעקרון, ה-GC הוא יישות עצמאית ומדי כמה זמן הוא אוסף את כל האובייקטים שמחקו אליהם refference. כמובן שהוא עושה את זה מתי שמתחשק לו (לא יודעת בדיוק מה החוקיות), אבל בכל מקרה ברגע שמחקת פויינטר למשהו, לא ניתן לגשת אליו מהתוכנית ולכן מבחינתך זה אמור להיות לא רלוונטי, כי כשיגיע הזמן ה-GC יפנה אותו.
אבל, אם אתה רוצה לאלץ את ה-GC לפנות זכרון שלא בשימוש, אז לפי שמצאתי זאת הדרך:
http://www.devdaily.com/java/edu/pj/pj010008

מסבירים שם, איך לקרוא באופן מפורש ל-GC על מנת שיפנה את הזכרון שלא בשימוש.

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

(4)
:אוקיי, אתה משתמש בשיטה של מערך של מצביעים?
אז כשתמחק את המצביע מהמערך זה יהיה בסדר.
הGC אחראי למחוק את זה בעצמו, מבחינתך זה מת

(5)
:באופן כללי כשעובדים עם סיסמאות רצוי לשמור אותם בצורת Hash ואז הבעיה נפתרת, כי מה שנשמר בזכרון זה רק ה-Hash של הסיסמא, ובכל בדיקה שהתוכנית מבצעת כדי לבדוק התאמה, היא מערבלת את הקלט ומשווה את תוצאת הערבול עם מה ששמור לה. בשיטה זו התוכנית לא "יודעת" מה היתה הסיסמא המקורית אלא רק מה תוצאת הערבול שלה - ובצורה כזו גם אם גונבים לה את הנתונים עדיין לא ניתן לדעת מה היתה הסיסמא.

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


למרות שההודעה האחרונה (מספר 6) קצת עומדת בניגוד למה שכתבתי בפסקה האחרונה של ההודעה המקורית (שנכתב על-סמך מה שכתוב בקישור שהבאתי)- שגם בשינוי ערכים עדיין נשמרים הערכים המקוריים כצל עד למחיקתם הסופית בהמשך.
אם מישהו יודע מה נכון (דיעה זו, או הדיעה שכתובה בהודעה 6) אשמח להארה..
29/04/2012 13:27:23 devil kide
אני לא יודע בדיוק איך עובד ג’אווה אז קח את מה שאני כותב בערבון מוגבל.
בכל מקרה, בוא נניח שיש לך מצביע על תא זיכרון שמספרו x שמכיל את הסיסמא שלך,
ברגע שתסיים את השימוש בסיסמא אתה יכול לדרוx את הערך שנמצא ב x בעזרת נתון אקראי כל שהוא.

בכל מקרה, אם למשתמש מסויים יש גישה פיסית למחשב שלך (או אפשרות להריץ קטע קוד) שישלוף מידע מהזיכרון הוא יוכל לכתוב אותה מידה תוכנית שתעקוב אחר ההקלדות שלך ובצורה הזו להגיע לסיסמא.
29/04/2012 15:00:35 ורנון
אני איש דוטנט :<
עמודים: 1