ช่องคงเปิดสำหรับการรวบรวมขยะหรือไม่


96

ให้คลาสยูทิลิตี้สมมุติที่ใช้ในการตั้งค่าโปรแกรมเท่านั้น:

class MyUtils {
   private static MyObject myObject = new MyObject();
   /*package*/static boolean doStuff(Params... params) {
       // do stuff with myObject and params...
   }
}

myObject จะถูกเก็บรวบรวมเมื่อไม่มีการใช้งานอีกต่อไปหรือไม่หรือจะคงอยู่ตลอดชีวิตของโปรแกรม?

คำตอบ:


113

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

ตรวจสอบJLS หัวข้อ 12.7 การยกเลิกการโหลดคลาสและอินเทอร์เฟซ

คลาสหรืออินเทอร์เฟซอาจถูกยกเลิกการโหลดหากและเฉพาะในกรณีที่ตัวโหลดคลาสที่กำหนดไว้อาจถูกเรียกคืนโดยตัวรวบรวมขยะ [... ] คลาสและอินเตอร์เฟสที่โหลดโดยตัวโหลดบูตสแตรปอาจไม่ถูกยกเลิกการโหลด


@bruno ตามลิงค์ของคุณหมายความว่าตัวโหลดคลาสมีการอ้างอิงถึงคลาสแต่ละคลาสที่โหลดแม้ว่าคลาสที่โหลดจะไม่มีสมาชิกแบบคงที่
Pacerier

@brunoconde ฉันไม่คิดว่ามันเป็นเรื่องจริง วรรคใดระบุว่า? (โปรดสนทนาต่อในstackoverflow.com/questions/405364/… )
Pacerier

เมื่อใดที่ตัวโหลดคลาสจะมีสิทธิ์ได้รับการรวบรวมขยะ เหรอ?
Rohit Bandil

@RohitBandil - เมื่อไม่สามารถเข้าถึงได้
Stephen C

55

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


1
Classอบเจ็กต์ที่ไม่มีตัวแปรคงถูกอ้างอิงโดยตัวโหลดคลาสหรือไม่
Pacerier

14

หากคุณต้องการใช้วัตถุชั่วคราวสำหรับการเริ่มต้นแบบคงที่แล้วกำจัดทิ้งคุณสามารถใช้บล็อกตัวเริ่มต้นแบบคงที่เช่น

class MyUtils {
   static
   {
      MyObject myObject = new MyObject();
      doStuff(myObject, params);
   }

   static boolean doStuff(MyObject myObject, Params... params) {
       // do stuff with myObject and params...
   }
}

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


13

myObject เป็นข้อมูลอ้างอิงและไม่ได้เป็นวัตถุ วัตถุจะถูกรวบรวมโดยอัตโนมัติเมื่อไม่มีการอ้างอิงชี้ไปที่วัตถุนั้นเนื่องจากไม่สามารถเข้าถึงได้

ดังนั้นวัตถุที่อยู่เบื้องหลังการอ้างอิงแบบคงที่ "myObject" สามารถเก็บรวบรวมขยะได้หากคุณยกเลิกการอ้างอิงด้วย

myObject = null;

และไม่มีการอ้างอิงอื่น ๆ เกี่ยวกับวัตถุนี้

อย่างไรก็ตามการอ้างอิงและตัวแปรคงยังคงอยู่ตลอดอายุการใช้งานของโปรแกรมของคุณ


ยินดีต้อนรับสู่ StackOverflow! การตั้งค่าวัตถุไว้nullที่ส่วนท้ายของstatic blockเป็นตัวเลือกที่ทำงานได้ ในกรณีของฉันอายุการใช้งานของวัตถุต้องนานกว่าบล็อกคงที่ การสิ้นประโยชน์ของวัตถุไม่เป็นรูปธรรมมากนัก ดังนั้นคำถามของฉันเกี่ยวกับการใช้เครื่องเก็บขยะ
Michael Deardeuff

7

ฉันคิดว่าสิ่งนี้ตอบคำถามของคุณ - โดยพื้นฐานแล้วไม่ใช่เว้นแต่ว่าคลาสนั้นมาจากตัวโหลดคลาสพิเศษและจะยกเลิกการโหลดคลาส


0

กุญแจสำคัญที่นี่คือ Garbage Collection of Class Instances เช่น Objects อินสแตนซ์ ClassLoader โดยพื้นฐานแล้วคือ Object ดังนั้นหากอ็อบเจ็กต์ Classloader ไม่ได้ถูกเก็บรวบรวมการอ้างอิงใด ๆ ที่เก็บไว้ในฮีป (เช่นของคงที่) แทบจะไม่ถูกรวบรวม ข้อยกเว้นคือ String pool

ดังนั้นก่อนที่คุณจะตัดสินใจทำอย่างกะทันหัน private static MyGiantClass myGiantObject = new MyGiantClass() เพราะฉันได้เรียนรู้วิธีที่ยากลำบาก

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