שאלות הזויות שנשאלתי לאחרונה

user32

Well-known member
מנהל
שאלות הזויות שנשאלתי לאחרונה

במסגרת תפקידי אני מתראיין באופן קבוע בערך אחת לחצי שנה. אחרי שחשבתי ששמעתי הכל, הצליחו להתקיל אותי במגרש הביתי. אני תוהה האם השאלות סופר קטנוניות או שיש לי צורך בהשלמת ידע. אז ככה: אובייקט שנוצר בג'אווה ועף Exception בקונסטרקטור, מה יהיה דינו מבחינת GC? האם הוא יהיה אובייקט "מקולקל" בזיכרון עד שיימחק? או שלא יווצר מההתחלה? ועוד יותר גרוע: מעבר לזה שכמעט לא משתמשים בfinallyze כי אף אחד לא מבטיח שהוא ייקרא עד סוף הריצה (זה סוג של destructor שנקרא כשהGC מנקה את האובייקט ואם כאשר הוא מנקה אותו). השאלה היתה האם אפשר "להחיות" אובייקט שהfinallyze שלו נקרא? כלומר, נגיד שאני מייצר רפרנס לאובייקט בתוך הfinallyze מה יקרה? היו עוד הרבה שאלות עומק כמו אופן פעולת הsynchronize ושיטות שונות לסנכרון threads, איך הGC עובד בשלל האלגוריתמים שלו, מתי הוא ינעל את על התהליכים במערכת ומדוע? וכו'. אגב, המראיינים היו כולם אנשי C וRT מה שקצת מסביר את השאלות... היו לי תשובות שניחשתי בהגיון מושכל. בסוף קיבלו אותי לדעתי בגלל שביחס לאחרים כנראה שהייתי המוביל אבל כבר התחייבתי לפרוייקט אחר אז נאלצתי לסרב בנימוס. מה אתם חושבים על השאלות? קצת מוזר, לא?
 

mulix

New member
תלוי

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

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

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

zaske

New member
אתה הולך לעשות פרוייקט לכור בנאתנז?

לא יפה, חשבתי שרק אני עוכר ישראל. שמע, אני מעריך שב99 אחוז מהמשרות לא צריך לדעת מה ששאלו לך. רוב הדברים אין לי מושג בעצמי - ולכן אנחש (בטח אני הולך להכשל פה) - א. לדעתי האובייקט עם ה exception לא ישמר - לא רואה שום הגיון לשמור אובייקט מקולקל (אוקיי, אולי זה יכול לתת קצת performance, אבל באמת שלא רואה סיבה אחרת לשמור) ב. מכיון שהאובייקט כבר סומן לפינוי, ולכן ה finalize נקרא , האובייקט בסופו של דבר כן יפונה - כי בשלב הקריאה ל finalize כמות ההצבעות אליו היתה אפס. ג. אשמח אם תרחיב על יתר השאלות , ותגיד לי האם קיבלתי 0, 50, או 100 לגבי א וב (הימור שלי - 0).
 
התשובה שלך ל-א. לא מתיישבת עם ההיגיון

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

zaske

New member
לא הבהרתי את עצמי

התכוונתי שהוא לא ישמר כאוביקט מקולקל בשביל ה GC. נראה לי שזה היה הדגש בשאלה הראשונה. כשכתבתי "לא יווצר" התכוונתי לסיום תהליך ההקצאה, ולא לשלב ביניים, כמו שאתה פירטת (אגב, מסכים איתך פה,התחושה שלי שזה מה שיקרה).
 
אני גם אנחש יצירה של אובייקט מורכבת משני צעדים: הקצאת מקום בזיכרון עבורו, והרצת הקונסטרקטור. Exception בקונסטרקטור עוצר את ריצת הקונסטרקטור, אבל לא משחרר את הזיכרון. לכן אני מנחש שישאר אובייקט מקולקל ובלתי-נגיש בזיכרון עד שה GC יגיע לשחרר אותו, בדיוק כמו כל אובייקט בלתי-נגיש אחר. לגבי ה finalize, זו שאלה יפה מאוד. עקרונית, finalize נקרא ע"י ה GC אחרי שהוא החליט כבר לשחרר את האובייקט. לכן אפשר לטעון שאי אפשר לעצור את הרכבת ושהשחרור יתבצע בכל מקרה. אולם זה פותח פתח ל security violation - זה נותן אפשרות לאפליקציה להשיג reference לאובייקט שכבר שוחרר, ולמעשה למרחב זיכרון שאחר כך אולי ישמש לצרכים אחרים לגמרי. אם היה מתאפשר כזה דבר, זה היה נותן back door שבעזרתו תוכנית JAVA תוכל לפרוץ את ה sandbox שלה, ולכן אני משער שהכניסו הגנות ב GC נגד זה. לכן אני מנחש שה GC מקבל החלטה לגבי אובייקט, מריץ את finalize, ואח"כ בודק שוב את ה referernce count שלו ורק אם הוא עדיין אפס משחרר אותו. אין לשאלות האלו שום משמעות פרקטית לגבי בחינת מועמדים לתפקיד כזה או אחר. אולי הן כן מעידות על מישהו ממש סקרן שלמד את ה internals של המימוש של ה JVM.
 
למעשה גם השאלה הראשונה היא security hole אם exception בקונסטרקטור היה גורם לכך שהזיכרון היה לא-מוקצה כלל, אז קוד כזה:
Foo o; try { o = new Foo(); } catch (...)​
תסלחו לי על הסינטקס הלא-מדויק, אני רק מנסה להעביר רעיון, אני לא איש JAVA, אבל קוד כזה, במקרה ו Foo לא הוקצה מעולם, יגרום לרפרנס להצביע לזיכרון לא-מוקצה, שיכול בשלב יותר מאוחר להיות מוקצה למטרות אחרות, וזה security violation.
 

korma1

New member
ההסברים שלך די יפים בתור אחד שאינו ג'אוואיסט

למיטב זכרוני, ניתן להחיות אובייקט ( Resurrection) בשלב ה-finalize אך לאחר ההחיאה, לא תתבצע קריאה נוספת ל-finalize בזמן שחרורו. גם זוכר שרק לאחר תום הקצאת האובייקט והרצת הבנאי ייווצר רפרנס נגיש לאובייקט עצמו ולכן bad practice הוא להכניס לוגיקה ואתחולים מורכבים לתוך הבנאי, שכן מבצעים פעולות נניח כבדות לעתים על אובייקט שטרם נוצר.
 
אני איש C ו- RT /Embedded כנראה כמו האנשים ששאלו את user32 את השאלות המוזרות האלו. לאיש C זה הגיוני לרצות לדעת איך בדיוק הנס הרפואי הזה של GC פועל בכלל, בעוד שלאיש JAVA זו נראית, ובצדק, טרחנות מיותרת וחסרת טעם.
 

zalomon

New member
לא מדויק

משום שהשורה רצה right to left: קודם רץ ה-constructor. אם הוא מצליח, מתבצעת ההשמה. אם הוא נכשל, ההשמה עצמה לא מתקיימת ועוברים ל-catch. הערך של o יהיה בהכרח null. (ככה זה ב-java)
 

עו9ר

New member
אבל ככה זה כן היה עובד

public class Foo { public Foo() { SecurityManager sm = System.getSecurityManager(); if(sm != null) { FilePermission fp = new FilePermission("index", "write"); sm.checkPermission(fp); // throws Access denied exception if permissions not granted } } } public class BadFoo extends Foo { static Foo foo; public BadFoo() { super(); } public void finalize() { foo = this; } public static void main(String[] args) { try { new BadFoo(); } catch(Exception e) { ...; } System.gc(); System.runFinalization(); // continue work with foo even that it doesn't have the permissions ....! } }​
 

user32

Well-known member
מנהל
מסכים בהחלט. זו היתה גם התשובה שלי

הקונסטרקטור הוא בסה"כ פונקציה לכל דבר שנקראת אחרי שהאובייקט מוקצה. אם לחשוב כמו C++ הרי שאחרי ההקצאה של new נוצר אובייקט בזיכרון ולdelete יקרא רק הGC כך שהקונסטרקטור יעוף אבל האובייקט יישאר. גם בדיבאגר כשמדבאגים את הקונסרקטור רואים שיש אובייקט עם כתובת והכל (מן הסתם...) ונקראת פונקציה בשם init בcall stack. על העניין של אבטחה לא חשבתי אבל זה נשמע הגיוני. כמו שכתבת: הרעיון היה לבחון ידע על דרך פעולת הJVM. היו גם עוד שאלות כמו צורת המימוש של סינכרונים בג'אווה שלא על כולם ידעתי לענות.
 

vinney

Well-known member
מסוג השאלות הבלתי רלוונטיות בעליל לתפקיד

ונועדו לבדוק בעיקר את יצר הסקרנות ו/או הגיון בריא.
 

zaske

New member
ההנחה שלי לגבי א היא -

אוקיי, נזרק exception - jvm תופס אותו. למה לשמור אובייקט מקולקל בזכרון? בשביל מה זה טוב? אבל כמו שהבהרתם לי, אני כנראה טועה (רק מסביר את צורת החשיבה שלי).
 
למעלה