JavaRush /จาวาบล็อก /Random-TH /วงจรชีวิตของวัตถุ

วงจรชีวิตของวัตถุ

เผยแพร่ในกลุ่ม
สวัสดี! ฉันคิดว่าคุณจะไม่แปลกใจเกินไปถ้าเราบอกคุณว่าขนาดหน่วยความจำในคอมพิวเตอร์ของคุณมีจำกัด :) แม้แต่ฮาร์ดไดรฟ์ซึ่งมีขนาดใหญ่กว่า RAM หลายเท่าก็ยังสามารถรองรับเกมโปรด ซีรีย์ทางทีวี และอื่น ๆ เพื่อป้องกันไม่ให้สิ่งนี้เกิดขึ้น คุณต้องตรวจสอบสถานะปัจจุบันของหน่วยความจำและลบไฟล์ที่ไม่จำเป็นออกจากคอมพิวเตอร์ของคุณ การเขียนโปรแกรม Java เกี่ยวข้องอะไรกับทั้งหมดนี้? โดยตรง! ท้ายที่สุดแล้ว เมื่อวัตถุใด ๆ ถูกสร้างขึ้นโดยเครื่อง Java หน่วยความจำจะถูกจัดสรรให้กับวัตถุนั้น ในโปรแกรมขนาดใหญ่จริง ๆ จะมีการสร้างอ็อบเจ็กต์นับหมื่นนับแสนรายการ ซึ่งแต่ละอ็อบเจ็กต์จะมีการจัดสรรหน่วยความจำของตัวเอง วงจรชีวิตของวัตถุ - 1แต่คุณคิดว่าวัตถุเหล่านี้มีอยู่นานแค่ไหน? พวกเขา “ใช้งาน” ตลอดเวลาที่โปรแกรมของเราทำงานอยู่หรือไม่? ไม่แน่นอน ด้วยข้อดีทั้งหมดของอ็อบเจ็กต์ Java พวกมันจึงไม่ใช่อมตะ :) วัตถุมีวงจรชีวิตของตัวเอง วันนี้เราจะพักจากการเขียนโค้ดสักหน่อยแล้วมาดูกระบวนการนี้กันดีกว่า :) ยิ่งไปกว่านั้น การทำความเข้าใจการทำงานของโปรแกรมและการจัดการทรัพยากรเป็นสิ่งสำคัญมาก แล้วชีวิตของวัตถุจะเริ่มต้นที่ไหน? เหมือนคน - ตั้งแต่แรกเกิดนั่นคือการสร้าง
Cat cat = new Cat();//вот сейчас и начался vital цикл нашего an object Cat!
ขั้นแรก Java Virtual Machine จะจัดสรรจำนวนหน่วยความจำที่จำเป็นเพื่อสร้างอ็อบเจ็กต์ จากนั้นเธอก็สร้างลิงก์ไปยังลิงก์นั้น ในกรณีของเรา - catเพื่อให้สามารถติดตามได้ หลังจากนี้ ตัวแปรทั้งหมดจะถูกเตรียมใช้งาน ตัวสร้างจะถูกเรียก และดูเถิด วัตถุใหม่ของเรามีชีวิตเป็นของตัวเองอยู่แล้ว :) อายุขัยของวัตถุนั้นแตกต่างกัน ไม่มีตัวเลขที่แน่นอนที่นี่ ไม่ว่าในกรณีใดมันจะอยู่ในโปรแกรมและทำหน้าที่ของมันในบางครั้ง พูดให้ถูกคือ วัตถุจะ “มีชีวิต” ตราบใดที่ยังมีการอ้างอิงถึงวัตถุนั้น ทันทีที่ไม่มีลิงก์เหลืออยู่ วัตถุก็จะ "ตาย" ตัวอย่างเช่น:
public class Car {

   String model;

   public Car(String model) {
       this.model = model;
   }

   public static void main(String[] args) {
       Car lamborghini  = new Car("Lamborghini Diablo");
       lamborghini = null;

   }

}
ในวิธีการดังกล่าวmain()วัตถุในรถ Lamborghini Diablo จะหยุดมีชีวิตอยู่ในบรรทัดที่สองแล้ว มีเพียงลิงก์เดียวเท่านั้น และตอนนี้ลิงก์นี้ได้ถูกมอบหมายnullแล้ว เนื่องจากไม่มีการอ้างอิงถึง Lamborghini Diablo จึงกลายเป็น "ขยะ" ไม่จำเป็นต้องรีเซ็ตลิงก์:
public class Car {

   String model;

   public Car(String model) {
       this.model = model;
   }

   public static void main(String[] args) {
       Car lamborghini  = new Car("Lamborghini Diablo");

       Car lamborghiniGallardo = new Car("Lamborghini Gallardo");
       lamborghini = lamborghiniGallardo;
   }

}
ที่นี่เราสร้างออบเจ็กต์ที่สอง หลังจากนั้นเรานำข้อมูลอ้างอิงlamborghiniและกำหนดให้กับออบเจ็กต์ใหม่นี้ ขณะนี้Lamborghini Gallardoมีการอ้างอิงสองรายการที่ชี้ไปที่วัตถุ แต่Lamborghini Diabloไม่มีการอ้างอิงถึงวัตถุ วัตถุนั้นจึงDiabloกลายเป็นขยะ และในขณะนี้กลไก Java ในตัวที่เรียกว่าตัวรวบรวมขยะหรืออีกนัยหนึ่ง - Garbage Collector, GC ได้เริ่มทำงานแล้ว
วงจรชีวิตของวัตถุ - 2
ตัวรวบรวมขยะเป็นกลไก Java ภายในที่รับผิดชอบในการเพิ่มหน่วยความจำนั่นคือการลบวัตถุที่ไม่จำเป็นออกไป ไม่ใช่เพื่ออะไรที่เราเลือกภาพที่มีเครื่องดูดฝุ่นหุ่นยนต์มาบรรยาย ท้ายที่สุดแล้ว ตัวรวบรวมขยะทำงานในลักษณะเดียวกัน: ในเบื้องหลัง มันจะ "เดินทาง" ผ่านโปรแกรมของคุณ เก็บขยะ และในขณะเดียวกันคุณก็แทบไม่ได้โต้ตอบกับมันเลย หน้าที่ของมันคือการลบวัตถุที่ไม่ได้ใช้อีกต่อไปในโปรแกรม ดังนั้นจึงทำให้หน่วยความจำในคอมพิวเตอร์ว่างสำหรับวัตถุอื่น คุณจำตอนต้นของการบรรยายได้ไหมว่าในชีวิตปกติคุณต้องตรวจสอบสถานะของคอมพิวเตอร์และลบไฟล์เก่า ดังนั้นในกรณีของอ็อบเจ็กต์ Java ตัวรวบรวมขยะจะทำสิ่งนี้เพื่อคุณ Garbage Collector ถูกเปิดใช้งานหลายครั้งระหว่างการทำงานของโปรแกรม: ไม่จำเป็นต้องเรียกมันโดยเฉพาะและออกคำสั่ง แม้ว่าจะเป็นไปได้ในทางเทคนิคก็ตาม ภายหลังเราจะพูดคุยเพิ่มเติมเกี่ยวกับเรื่องนี้และวิเคราะห์ขั้นตอนการทำงานโดยละเอียดยิ่งขึ้น ในขณะที่ผู้รวบรวมขยะมาถึงวัตถุก่อนที่จะถูกทำลายจะมีการเรียกวิธีพิเศษกับวัตถุ - finalize(). สามารถใช้เพื่อเพิ่มทรัพยากรเพิ่มเติมบางอย่างที่วัตถุกำลังใช้อยู่ วิธีการนี้เป็นfinalize()ของคลาส Objectนั่นคือ พร้อมด้วยequals()และที่คุณพบก่อนหน้านี้ วัตถุใดๆ ก็มีสิ่งhashCode()นั้น toString()มันแตกต่างจากวิธีอื่นคือ... จะพูดยังไง... ไม่แน่นอนมาก กล่าวคือ มันไม่ได้ถูกเรียกก่อนที่จะทำลายวัตถุเสมอไป การเขียนโปรแกรมเป็นสิ่งที่แม่นยำ โปรแกรมเมอร์บอกให้คอมพิวเตอร์ทำอะไรบางอย่าง และคอมพิวเตอร์ก็ทำเช่นนั้น คุณอาจคุ้นเคยกับพฤติกรรมนี้แล้ว และในตอนแรกอาจเป็นเรื่องยากสำหรับคุณที่จะยอมรับแนวคิด: “ก่อนที่วัตถุจะถูกทำลาย วิธี finalize()การเรียน จะถูกเรียกว่า Object. หรือไม่ก็เรียกว่า.. ถ้าเราโชคดี!” อย่างไรก็ตามนี่เป็นเรื่องจริง เครื่อง Java จะกำหนดว่าจะเรียกใช้เมธอดfinalize()ในแต่ละกรณีหรือไม่ ตัวอย่างเช่น ลองเรียกใช้โค้ดต่อไปนี้เพื่อการทดลอง:
public class Cat {

   private String name;

   public Cat(String name) {
       this.name = name;
   }

   public Cat() {
   }

   public static void main(String[] args) throws Throwable {

       for (int i = 0 ; i < 1000000; i++) {

           Cat cat = new Cat();
           cat = null;//вот здесь первый an object становится доступен сборщику мусора
       }
   }

   @Override
   protected void finalize() throws Throwable {
       System.out.println("Объект Cat уничтожен!");
   }
}
เราสร้างออบเจ็กต์Catและในโค้ดบรรทัดถัดไปเราจะรีเซ็ตการอ้างอิงเดียวเท่านั้น และอีกล้านครั้ง เราได้ลบล้างเมธอดนี้อย่างชัดเจนfinalize()และควรพิมพ์สตริงไปยังคอนโซลล้านครั้งในแต่ละครั้งก่อนที่จะทำลายCatอ็อบเจ็กต์ แต่ไม่มี! พูดให้ถูกคือมันรันบนคอมพิวเตอร์ของฉันเพียง 37,346 ครั้งเท่านั้น! นั่นคือมีเพียง 1 กรณีจาก 27 เครื่องเท่านั้นที่เครื่อง Java ที่ฉันติดตั้งตัดสินใจที่จะเรียกใช้เมธอดfinalize()- ในกรณีอื่น ๆ การรวบรวมขยะจะดำเนินการโดยไม่มีสิ่งนี้ ลองใช้โค้ดนี้ด้วยตัวเอง: ส่วนใหญ่แล้วผลลัพธ์จะแตกต่างออกไป อย่างที่คุณเห็นfinalize()เป็นการยากที่จะเรียกว่าพันธมิตรที่เชื่อถือได้ :) ดังนั้น คำแนะนำเล็กๆ น้อยๆ สำหรับอนาคต: คุณไม่ควรพึ่งพาวิธีการนี้finalize()ในกรณีที่ต้องปล่อยทรัพยากรที่สำคัญบางอย่างออกไป บางที JVM อาจจะเรียกมันว่าอาจจะไม่ ใครจะรู้? หากในช่วงอายุการใช้งานอ็อบเจ็กต์ของคุณใช้ทรัพยากรบางอย่างที่มีความสำคัญอย่างยิ่งต่อประสิทธิภาพการทำงาน เช่น มันยังคงเชื่อมต่อกับฐานข้อมูลแบบเปิด จะเป็นการดีกว่าที่จะสร้างวิธีพิเศษในคลาสของคุณเพื่อปลดปล่อยพวกมันและเรียกมันอย่างชัดเจนเมื่อวัตถุนั้น ไม่ต้องการอีกต่อไป. ด้วยวิธีนี้คุณจะรู้ได้อย่างแน่นอนว่าประสิทธิภาพของโปรแกรมของคุณจะไม่ได้รับผลกระทบ ในตอนแรกเราบอกว่าการจัดการหน่วยความจำและการกำจัดขยะมีความสำคัญมากและนี่ก็เป็นจริง การจัดการทรัพยากรที่ไม่เหมาะสมและการขาดความเข้าใจในกระบวนการประกอบวัตถุที่ไม่จำเป็นอาจทำให้หน่วยความจำรั่วได้ นี่เป็นหนึ่งในข้อผิดพลาดในการเขียนโปรแกรมที่มีชื่อเสียงที่สุด โค้ดที่เขียนไม่ถูกต้องโดยโปรแกรมเมอร์อาจส่งผลให้หน่วยความจำใหม่ถูกจัดสรรในแต่ละครั้งสำหรับอ็อบเจ็กต์ที่สร้างขึ้นใหม่ ในขณะที่อ็อบเจ็กต์เก่าที่ไม่จำเป็นจะไม่สามารถลบออกได้โดยตัวรวบรวมขยะ เนื่องจากเราทำการเปรียบเทียบกับเครื่องดูดฝุ่นหุ่นยนต์ ลองจินตนาการว่าจะเกิดอะไรขึ้นก่อนที่จะเริ่มใช้งานหุ่นยนต์ หากคุณกระจายถุงเท้าไปรอบๆ บ้าน ทำลายแจกันแก้ว และทิ้งชุดเลโก้ที่แยกชิ้นส่วนไว้บนพื้น แน่นอนว่าหุ่นยนต์จะพยายามทำอะไรบางอย่าง แต่เมื่อถึงจุดหนึ่งหุ่นยนต์ก็จะติดขัด
วงจรชีวิตของวัตถุ - 3
เพื่อให้ทำงานได้อย่างถูกต้อง คุณต้องรักษาพื้นให้อยู่ในสภาพดีและกำจัดทุกอย่างออกจากตรงนั้นซึ่งเครื่องดูดฝุ่นไม่สามารถจัดการได้ คนเก็บขยะทำงานบนหลักการเดียวกัน หากมีสิ่งของเหลืออยู่ในโปรแกรมที่ไม่สามารถรวบรวมได้ (เช่น ถุงเท้าหรือเลโก้สำหรับหุ่นยนต์ดูดฝุ่น) เมื่อถึงจุดหนึ่งหน่วยความจำก็จะหมด และไม่เพียงแต่โปรแกรมที่คุณเขียนเท่านั้นที่จะค้าง แต่ยังรวมถึงโปรแกรมอื่น ๆ ทั้งหมดที่ทำงานบนคอมพิวเตอร์ในขณะนั้นด้วย หน่วยความจำก็จะไม่เพียงพอสำหรับพวกเขาเช่นกัน นี่คือลักษณะวงจรชีวิตของอ็อบเจ็กต์และตัวรวบรวมขยะใน Java ไม่จำเป็นต้องจดจำสิ่งนี้: เพียงแค่เข้าใจหลักการทำงาน ในการบรรยายครั้งต่อไป เราจะพูดถึงกระบวนการเหล่านี้โดยละเอียด แต่สำหรับตอนนี้ คุณสามารถกลับไปแก้ไขปัญหา JavaRush ได้แล้ว :) โชคดี!
ความคิดเห็น
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION