תגידו, זה רעיון טוב לתפוס OutOfMemory ולהמשיך ?

TakeCtrl

New member
תגידו, זה רעיון טוב לתפוס OutOfMemory ולהמשיך ?


לא בא ממני , אני פשוט רואה את הImageIcon עושה את זה לאחר שאני רואה אותו עושה printStackTrace לכל Exception , לאחר שאני קורא כמה קבצים.
והסיבה שהוא עושה את זה כי יש לו איזה thread ברקע שמתחיל לעבד אותם, כך שהnew מחביא המון שרצים.
הצרה היא שגיליתי שבjava6 הוא מסוגל למצוא jpeg מסוג מסויים שImageIo לא מסוגל.
 

vinney

Well-known member
יש סיכוי שתתאושש?

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

TakeCtrl

New member
זה serverside, מה שמותר גרוע, שבImageIcon אתה לא מקבל

שום שגיאה, הוא פשוט תופס את הOOM ואתה רואה את זה רק בlog של הServiceWrapper שמיועד לconsole ואתה גם לא יודע מתי זה קרה כי כל העסק עובד לך בצורה אנסיכרונית.
http://pag-www.gtisc.gatech.edu/chord/examples/jdk/sun/awt/image/ImageFetcher.java.html
(חפש printStackTrace).
&nbsp
בImageIO לפחות אתה לא אמור לקבל בOOM , כי העסק סינכרוני, אבל אתה יכול לפחות לרשום ללוג מה קרה ולצרף את הimage שזה קרה בו, אבל ראיתי עכשיו מקרים שהוא נופל בתמונות שimageIcon רק מדפיס הודעה שם אבל עדיין מצליח לקרוא מימדים.
אפשר תמיד לנסות קודם עם ImageIo ואם הוא נופל בImageIcon, אבל זה רק מגביר את הסיכון של OOM במקרה של שיש יותר images שנופלים imageIO.
 

vinney

Well-known member
איזה מזל שאני לא כותב בJAVA...

הקצאה אחת נכשלת מעיפה לכם את כל הפריימוורק? איזה מין דבר זה?
&nbsp
נראה לי קצת הזוי.
 

TakeCtrl

New member
ואללה, פתחת חבית pandora... :)

זה לא הקצאה אחת,נתקלתי בזה לאחר שקראתי 10-20 קבצים, תתחיל לקרוא המוני קבצים בינארים ותשמור אותם בזיכרון, לא תיתן הזדמנות לGC לנקות אותם כי אתה עדיין שומר להם reference, איפה תרצה שישים לך הקצאות נוספות? על הראש? אפילו היה לי אפשרות לתפוס ולהתאושש לא הייתי רוצה כי זה אומר שמשהו בסיס דפוק באפליקציה.
 

vinney

Well-known member
אני אפילו יודע בדיוק מה דפוק באפליקציה


מה שאתה בעצם אומר הוא שאתה מעלה אינספור קבצים לזכרון בלי לשחרר עד שבסוף נגמר לך הזכרון...
&nbsp
במצב הזה באמת אין הרבה מה לעשות חוץ מלסגור את הבסטה. חשבת אולי לשחרר את ההקצאות הקודמות?
&nbsp
זה נראה לי כמו בעית ארכיטקטורה/דיזיין, לא שאלה טכנית של אם לתפוס או לא לתפוס. OOM זה משהו שעקרונית לא אמור לקרות, ולפי מה שאתה מתאר - אצלך זה קורה by design...
 

TakeCtrl

New member
by ... design...של java

ספריית הimage של java ידועה בתור משהו די דפוק... למען האמת יש 2 כאלה..
הראשונה של awt כנראה יותר דפוקה מהחדשה יותר ImageIO ..
 

user32

Well-known member
מנהל
זה אכן לא מה שקורה

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

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

user32

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

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

TakeCtrl

New member
tell me about it , היו לנו כבר כמה וכמה מקרים כאלה :/

בהתחלה חשבנו שזה בגלל שנתנו פחות זיכרון למערכת הפעלה (יש סקריפט שמגדיר xms, ו xmx בהתאם לגודל הזיכרון שאתה נותן לו בvsphere בהתחלה הוא נתן השאיר רק 1gb למערכת עצמה וכל השאר נתן ל xms, הגדלנו את זה ל3gb).
&nbsp
זה כמעט פתר את זה...
 

pattos

New member
מעיפה את החוט, כי זה Error ואף אחד לא תופס אותו בד"כ

שאר החוטים רצים ממה שאני זוכר
 
פעם כתבתי לשעון חכם של פבל

שמריץ customized FreeRTOS kernel.
אם הקצנו זיכרון אחרי שהתוכנית רצה ולא היה מספיק זכרון המלוק בפועל היה מעיף את כל התוכנית (במקום להחזיר NULL). שעות של תסכול גרם לי הבאג הזה.
 

BravoMan

Active member
אם אתה יכול להמשיך, אז למה לא להמשיך?

אני בדעה שכבר נכתבה פה - אם אתה יכול להימנע מקריסה טוטלית, ולבצע פעולה מסודרת כלשהי במקום, זה הדבר הנכון לעשות.
&nbsp
למיטב הבנתי (ויתקנו אותי אחרים כאן כי לא פיתחתי ב-Java צד שרת), ה-OOM נזרק אם ההקצאה המבוקשת גדולה מהזיכרון הפנוי.
זה אומר, שהקצאות קטנות יותר עדיין יכולות להצליח.
&nbsp
ולגבי הספריות הספציפיות שציינת:
לא ממש הבנתי מהיכן מגיעות התמונות ולמה להשתמש בספריות כאלה בצד שרת?
למיטב הבנתי אלה ספריות לצד Client שנועדו לאפשר תצוגה.
&nbsp
על פניו, אם מדובר בקבצים שמשתמשים מעלים, תמיד יכול להיות מצב שהקובץ נבנה בכוונה בצורה שתגרום למי שינסה לפתוח אותו לקרוס, אחרי הכל גם בספריות וותיקות ובדוקות שמתעסקות עם אלגוריתמים לדחיסה מורכבים כמו זה של jpeg לא פעם יש חורים.
&nbsp
כאמור, צד שרת הוא לא בתחום התמחותי, אבל אני מקבל הרגשה חזקה מכל מה שכתבת בשרשור הזה שאתה עושה משהו לא נכון - או שהשימוש שלך בספריות לא נכון, או שבכלל לא בטוח שכדאי להתעסק עם התמונות הבעייתיות...
 

TakeCtrl

New member
בסופו של דבר כל העסק עוד מה הרוחב ואורך בפיסקלים של התמונה

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

BravoMan

Active member
גם אני לא כי לא נזקקתי לכך, אבל זה משהו שיחסית

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

user32

Well-known member
מנהל
הרבה יותר יעיל

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