StackOverflowError ใน Java หรือไม่?


27

ฉันเคยคิดว่ามันไม่ได้ แต่เมื่อวานนี้ฉันต้องทำ มันเป็นแอพพลิเคชั่นที่ใช้Akka (ระบบการทำงานของนักแสดงสำหรับ JVM) เพื่อประมวลผลงานอะซิงโครนัส หนึ่งในนักแสดงทำการจัดการไฟล์ PDF บางส่วนและเนื่องจากห้องสมุดมีรถบั๊กมันก็ตายด้วยStackOverflowErrorทุก ๆ คราว

ด้านที่สองคือ Akka ได้รับการกำหนดค่าให้ปิดระบบนักแสดงทั้งหมดหากมีข้อผิดพลาดร้ายแรง JVM (เช่น StackOverflowError)

ประเด็นที่สามคือระบบนักแสดงนี้ถูกฝังอยู่ภายในเว็บแอพ (สำหรับ WTF-ish, มรดก, เหตุผล) ดังนั้นเมื่อระบบนักแสดงปิดตัวลงแอปพลิเคชันเว็บจะไม่ ผลกระทบสุทธิคือในStackOverflowErrorแอปพลิเคชันการประมวลผลงานของเรากลายเป็นเพียงเว็บแอปที่ว่างเปล่า

การแก้ไขอย่างรวดเร็วฉันต้องจับStackOverflowErrorการโยนเพื่อให้กลุ่มเธรดของระบบนักแสดงไม่ฉีกขาด นี่ทำให้ฉันคิดว่าบางทีมันก็โอเคที่จะจับข้อผิดพลาดโดยเฉพาะอย่างยิ่งในบริบทเช่นนี้? เมื่อใดที่มีเธรดพูลกำลังประมวลผลงานตามอำเภอใจ? ซึ่งแตกต่างจากOutOfMemoryErrorฉันไม่สามารถจินตนาการว่าStackOverflowErrorสามารถออกจากโปรแกรมที่อยู่ในสถานะที่ไม่สอดคล้องกัน สแต็กจะถูกล้างหลังจากข้อผิดพลาดดังกล่าวดังนั้นการคำนวณจึงสามารถดำเนินต่อได้ตามปกติ แต่บางทีฉันอาจพลาดสิ่งสำคัญไป

นอกจากนี้ขอให้สังเกตว่าฉันทั้งหมดเพื่อแก้ไขข้อผิดพลาดในสถานที่แรก (ตามความเป็นจริงฉันได้แก้ไข SOE ในแอพเดียวกันนี้เมื่อไม่กี่วันที่ผ่านมา) แต่ฉันไม่รู้จริง ๆ ว่าเมื่อใด สถานการณ์แบบนี้อาจเกิดขึ้นได้

เหตุใดจึงเป็นการดีกว่าที่จะเริ่มกระบวนการ JVM ใหม่แทนการจับStackOverflowErrorทำเครื่องหมายว่างานนั้นล้มเหลวและดำเนินธุรกิจของฉันต่อไป

มีเหตุผลที่น่าสนใจไหมที่จะไม่ใช้ SOE? ยกเว้น "แนวปฏิบัติที่ดีที่สุด" ซึ่งเป็นคำที่คลุมเครือซึ่งไม่ได้บอกอะไรเลย


1
อีกตัวเลือกหนึ่งคือการเพิ่มพื้นที่สแต็คที่มีอยู่ใน JVM
freet ratchet

3
@ratchetfreak: StackOverflowExceptions มักเกิดจากสายโซ่ที่ไม่สิ้นสุดของการเรียกเมธอด - การเพิ่มพื้นที่สแต็กจะเพิ่มต้นทุนหน่วยความจำของเธรดใหม่โดยไม่มีประโยชน์
jhominal

1
อย่างน้อยหนึ่ง SOE นั้นถูกต้องเพราะอินพุตมีขนาดใหญ่มาก โชคไม่ดีที่การจัดการมันด้วยการใช้งานแบบเรียกซ้ำ (regex ของ Java) ไม่ได้เป็นความคิดที่ดี อย่างไรก็ตามแม้ว่าการคำนวณจะรับประกันว่าจะยุติลงคุณไม่ทราบว่าขนาดสแต็กใหม่นั้นใหญ่พอสำหรับการคำนวณอื่น ๆ หรือไม่
Ionuț G. Stan

2
ไม่ควรย้ายไปที่ Sta นี้ ... โอ้รอ ... ไม่เป็นไร :-)
Blrfl

เกี่ยวกับห้องสมุดบั๊กกี้ของคุณ คุณควรโอนย้ายไฟล์ PDF ที่จัดการกับฟังก์ชั่นลงในกระบวนการของตัวเองเพื่อให้ระบบปฏิบัติการฆ่าได้
Esben Skov Pedersen

คำตอบ:


44

ตามกฎทั่วไปหากไม่เคยเป็นที่ยอมรับอย่างแน่นอนเคยทำบางสิ่งบางอย่างและมีข้อตกลงเกี่ยวกับเรื่องนั้นผู้ดำเนินการด้านภาษาจะไม่ได้รับอนุญาต เกือบจะไม่มีคติพจน์ที่ชัดเจนอย่างเป็นเอกฉันท์ดังกล่าว (โชคดีเพราะนั่นคือสิ่งที่ทำให้เราเป็นโปรแกรมเมอร์มนุษย์ในงาน!)

ดูเหมือนว่าคุณจะพบสถานการณ์ที่การจับข้อผิดพลาดนี้เป็นตัวเลือกที่ดีที่สุดสำหรับคุณ: มันช่วยให้แอปพลิเคชันของคุณทำงานในขณะที่ทางเลือกอื่น ๆ ไม่ได้ทำและนั่นคือสิ่งที่สำคัญที่สุด ทั้งหมด "วิธีปฏิบัติที่ดีที่สุด" เป็นเพียง summations จากประสบการณ์ที่ยาวนานกับหลายกรณีที่สามารถมักจะถูกนำมาใช้ในสถานที่ของการวิเคราะห์รายละเอียดของกรณีเฉพาะเพื่อประหยัดเวลา; ในกรณีของคุณคุณได้ทำการวิเคราะห์เฉพาะและได้ผลลัพธ์ที่แตกต่าง ขอแสดงความยินดีคุณมีความสามารถในการคิดอย่างอิสระ!

(ที่กล่าวว่ามีสถานการณ์ที่กองซ้อนมากเกินไปอาจทำให้แอปพลิเคชันไม่สอดคล้องกันเช่นหน่วยความจำหมดลองจินตนาการว่าวัตถุบางอย่างถูกสร้างขึ้นแล้วเริ่มต้นด้วยความช่วยเหลือของวิธีการซ้อนภายในเรียก - ถ้าหนึ่งในนั้นโยนวัตถุ อาจอยู่ในสถานะที่ไม่น่าจะเป็นไปได้ราวกับว่าการจัดสรรล้มเหลว แต่นั่นไม่ได้หมายความว่าโซลูชันของคุณจะไม่ดีที่สุด)


3
ขอบคุณ ความสงสัยของฉันค่อนข้างแข็งแกร่งหลังจากที่ฉันพบว่า. NET สร้างStackOverflowExceptionข้อยกเว้นที่ไม่สามารถตรวจจับได้ ฉันรู้ว่ามันเป็นแพลตฟอร์มที่แตกต่างกัน แต่ฉันคิดว่าพวกเขาอาจมีเหตุผล นอกจากนี้จุดของคุณสำหรับการเริ่มต้นวัตถุคือจุดที่ นี่ทำให้ฉันคิดว่าฉันควรจับ SOE นี้สองสามชั้นที่เป็นนามธรรมด้านล่างเพื่อที่ฉันจะไม่ได้เห็น SOE "ผิด"
Ionuț G. Stan

14
+1: แนวปฏิบัติที่ดีที่สุดควรมาพร้อมกับคำอธิบายว่าทำไมและในบริบทใดที่ "ดีที่สุด" เพื่อให้คุณสามารถตัดสินได้ว่าพวกเขานำไปใช้กับกรณีเฉพาะของคุณหรือไม่
Michael Borgwardt

situations heresituations whereควรจะเป็น
Servy

2

ฉันไม่รู้ว่ามีความเสี่ยงเฉพาะของ JVM หรือไม่ที่นี่ แต่โดยรวมแล้วดูเหมือนจะสมเหตุสมผล

ตัวอย่างเช่นมีอัลกอริทึมแบบเรียกซ้ำเช่น naive quicksort ที่มีlog(n)ความลึกของสแต็กในกรณีทั่วไป แต่ในกรณีที่เลวร้ายที่สุดพวกมันจะลดความลึกลงไปจนถึงระดับnที่สามารถระเบิดสแต็กได้

กรณีที่เลวร้ายที่สุดนั้นหายากและไม่น่าจะเกิดขึ้นอีกถ้าคุณรีสตาร์ทการเรียงลำดับในชุดที่เรียงลำดับบางส่วนดังนั้นจึงมีเหตุผลที่จะต้องตรวจจับข้อยกเว้นสแต็กล้นเมื่อเกิดขึ้นและรีสตาร์ททำงานแทนการพยายามป้องกันข้อผิดพลาด แอปพลิเคชันทั้งหมด

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.