สวัสดี! ฉันคิดว่าคุณจะไม่แปลกใจเกินไปถ้าเราบอกคุณว่าขนาดหน่วยความจำในคอมพิวเตอร์ของคุณมีจำกัด :) แม้แต่ฮาร์ดไดรฟ์ซึ่งมีขนาดใหญ่กว่า RAM หลายเท่าก็ยังสามารถรองรับเกมโปรด ซีรีย์ทางทีวี และอื่น ๆ เพื่อป้องกันไม่ให้สิ่งนี้เกิดขึ้น คุณต้องตรวจสอบสถานะปัจจุบันของหน่วยความจำและลบไฟล์ที่ไม่จำเป็นออกจากคอมพิวเตอร์ของคุณ การเขียนโปรแกรม Java เกี่ยวข้องอะไรกับทั้งหมดนี้? โดยตรง! ท้ายที่สุดแล้ว เมื่อวัตถุใด ๆ ถูกสร้างขึ้นโดยเครื่อง Java หน่วยความจำจะถูกจัดสรรให้กับวัตถุนั้น ในโปรแกรมขนาดใหญ่จริง ๆ จะมีการสร้างอ็อบเจ็กต์นับหมื่นนับแสนรายการ ซึ่งแต่ละอ็อบเจ็กต์จะมีการจัดสรรหน่วยความจำของตัวเอง แต่คุณคิดว่าวัตถุเหล่านี้มีอยู่นานแค่ไหน? พวกเขา “ใช้งาน” ตลอดเวลาที่โปรแกรมของเราทำงานอยู่หรือไม่? ไม่แน่นอน ด้วยข้อดีทั้งหมดของอ็อบเจ็กต์ Java พวกมันจึงไม่ใช่อมตะ :) วัตถุมีวงจรชีวิตของตัวเอง วันนี้เราจะพักจากการเขียนโค้ดสักหน่อยแล้วมาดูกระบวนการนี้กันดีกว่า :) ยิ่งไปกว่านั้น การทำความเข้าใจการทำงานของโปรแกรมและการจัดการทรัพยากรเป็นสิ่งสำคัญมาก แล้วชีวิตของวัตถุจะเริ่มต้นที่ไหน? เหมือนคน - ตั้งแต่แรกเกิดนั่นคือการสร้าง
ตัวรวบรวมขยะเป็นกลไก Java ภายในที่รับผิดชอบในการเพิ่มหน่วยความจำนั่นคือการลบวัตถุที่ไม่จำเป็นออกไป ไม่ใช่เพื่ออะไรที่เราเลือกภาพที่มีเครื่องดูดฝุ่นหุ่นยนต์มาบรรยาย ท้ายที่สุดแล้ว ตัวรวบรวมขยะทำงานในลักษณะเดียวกัน: ในเบื้องหลัง มันจะ "เดินทาง" ผ่านโปรแกรมของคุณ เก็บขยะ และในขณะเดียวกันคุณก็แทบไม่ได้โต้ตอบกับมันเลย หน้าที่ของมันคือการลบวัตถุที่ไม่ได้ใช้อีกต่อไปในโปรแกรม ดังนั้นจึงทำให้หน่วยความจำในคอมพิวเตอร์ว่างสำหรับวัตถุอื่น คุณจำตอนต้นของการบรรยายได้ไหมว่าในชีวิตปกติคุณต้องตรวจสอบสถานะของคอมพิวเตอร์และลบไฟล์เก่า ดังนั้นในกรณีของอ็อบเจ็กต์ Java ตัวรวบรวมขยะจะทำสิ่งนี้เพื่อคุณ Garbage Collector ถูกเปิดใช้งานหลายครั้งระหว่างการทำงานของโปรแกรม: ไม่จำเป็นต้องเรียกมันโดยเฉพาะและออกคำสั่ง แม้ว่าจะเป็นไปได้ในทางเทคนิคก็ตาม ภายหลังเราจะพูดคุยเพิ่มเติมเกี่ยวกับเรื่องนี้และวิเคราะห์ขั้นตอนการทำงานโดยละเอียดยิ่งขึ้น ในขณะที่ผู้รวบรวมขยะมาถึงวัตถุก่อนที่จะถูกทำลายจะมีการเรียกวิธีพิเศษกับวัตถุ -
เพื่อให้ทำงานได้อย่างถูกต้อง คุณต้องรักษาพื้นให้อยู่ในสภาพดีและกำจัดทุกอย่างออกจากตรงนั้นซึ่งเครื่องดูดฝุ่นไม่สามารถจัดการได้ คนเก็บขยะทำงานบนหลักการเดียวกัน หากมีสิ่งของเหลืออยู่ในโปรแกรมที่ไม่สามารถรวบรวมได้ (เช่น ถุงเท้าหรือเลโก้สำหรับหุ่นยนต์ดูดฝุ่น) เมื่อถึงจุดหนึ่งหน่วยความจำก็จะหมด และไม่เพียงแต่โปรแกรมที่คุณเขียนเท่านั้นที่จะค้าง แต่ยังรวมถึงโปรแกรมอื่น ๆ ทั้งหมดที่ทำงานบนคอมพิวเตอร์ในขณะนั้นด้วย หน่วยความจำก็จะไม่เพียงพอสำหรับพวกเขาเช่นกัน นี่คือลักษณะวงจรชีวิตของอ็อบเจ็กต์และตัวรวบรวมขยะใน Java ไม่จำเป็นต้องจดจำสิ่งนี้: เพียงแค่เข้าใจหลักการทำงาน ในการบรรยายครั้งต่อไป เราจะพูดถึงกระบวนการเหล่านี้โดยละเอียด แต่สำหรับตอนนี้ คุณสามารถกลับไปแก้ไขปัญหา JavaRush ได้แล้ว :) โชคดี!
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 ได้เริ่มทำงานแล้ว
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 อาจจะเรียกมันว่าอาจจะไม่ ใครจะรู้? หากในช่วงอายุการใช้งานอ็อบเจ็กต์ของคุณใช้ทรัพยากรบางอย่างที่มีความสำคัญอย่างยิ่งต่อประสิทธิภาพการทำงาน เช่น มันยังคงเชื่อมต่อกับฐานข้อมูลแบบเปิด จะเป็นการดีกว่าที่จะสร้างวิธีพิเศษในคลาสของคุณเพื่อปลดปล่อยพวกมันและเรียกมันอย่างชัดเจนเมื่อวัตถุนั้น ไม่ต้องการอีกต่อไป. ด้วยวิธีนี้คุณจะรู้ได้อย่างแน่นอนว่าประสิทธิภาพของโปรแกรมของคุณจะไม่ได้รับผลกระทบ ในตอนแรกเราบอกว่าการจัดการหน่วยความจำและการกำจัดขยะมีความสำคัญมากและนี่ก็เป็นจริง การจัดการทรัพยากรที่ไม่เหมาะสมและการขาดความเข้าใจในกระบวนการประกอบวัตถุที่ไม่จำเป็นอาจทำให้หน่วยความจำรั่วได้ นี่เป็นหนึ่งในข้อผิดพลาดในการเขียนโปรแกรมที่มีชื่อเสียงที่สุด โค้ดที่เขียนไม่ถูกต้องโดยโปรแกรมเมอร์อาจส่งผลให้หน่วยความจำใหม่ถูกจัดสรรในแต่ละครั้งสำหรับอ็อบเจ็กต์ที่สร้างขึ้นใหม่ ในขณะที่อ็อบเจ็กต์เก่าที่ไม่จำเป็นจะไม่สามารถลบออกได้โดยตัวรวบรวมขยะ เนื่องจากเราทำการเปรียบเทียบกับเครื่องดูดฝุ่นหุ่นยนต์ ลองจินตนาการว่าจะเกิดอะไรขึ้นก่อนที่จะเริ่มใช้งานหุ่นยนต์ หากคุณกระจายถุงเท้าไปรอบๆ บ้าน ทำลายแจกันแก้ว และทิ้งชุดเลโก้ที่แยกชิ้นส่วนไว้บนพื้น แน่นอนว่าหุ่นยนต์จะพยายามทำอะไรบางอย่าง แต่เมื่อถึงจุดหนึ่งหุ่นยนต์ก็จะติดขัด
GO TO FULL VERSION