JavaRush /Java Blog /Random-KO /객체 수명주기

객체 수명주기

Random-KO 그룹에 게시되었습니다
안녕하세요! 컴퓨터의 메모리 크기는 제한되어 있다고 말해도 별로 놀라지 않으실 것 같아요 :) RAM보다 몇 배 더 큰 하드 드라이브도 좋아하는 게임, TV 시리즈, 등등. 이런 일이 발생하지 않도록 하려면 현재 메모리 상태를 모니터링하고 컴퓨터에서 불필요한 파일을 삭제해야 합니다. 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. 람보르기니 디아블로에 대한 언급이 남아있지 않기 때문에 '정크'가 됩니다. 링크를 재설정할 필요는 없습니다.
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쓰레기가 된다. 그리고 이 순간 가비지 컬렉터, 즉 가비지 컬렉터(Garbage Collector, GC)라고 하는 내장된 Java 메커니즘이 작동됩니다.
객체 수명주기 - 2
가비지 수집기는 메모리 해제, 즉 메모리에서 불필요한 객체를 제거하는 내부 Java 메커니즘입니다. 이를 묘사하기 위해 로봇청소기가 있는 사진을 선택한 것은 괜한 일이 아니었습니다. 결국 가비지 컬렉터는 거의 같은 방식으로 작동합니다. 백그라운드에서는 프로그램을 통해 "이동"하고 가비지를 수집하며 동시에 사용자는 실제로 상호 작용하지 않습니다. 그 임무는 프로그램에서 더 이상 사용되지 않는 개체를 제거하는 것입니다. 따라서 다른 개체를 위해 컴퓨터의 메모리를 확보합니다. 강의 시작 부분에서 우리가 일상 생활에서 컴퓨터 상태를 모니터링하고 오래된 파일을 삭제해야 한다고 말한 것을 기억하십니까? 따라서 Java 개체의 경우 가비지 수집기가 이 작업을 수행합니다. 가비지 컬렉터는 프로그램이 작동하는 동안 여러 번 시작됩니다. 기술적으로는 가능하지만 구체적으로 호출하거나 명령을 내릴 필요는 없습니다. 나중에 우리는 이에 대해 더 자세히 이야기하고 작업 과정을 더 자세히 분석할 것입니다. 가비지 컬렉터가 객체에 도달하는 순간, 객체가 파괴되기 직전에 객체에 대해 특별한 메소드가 호출됩니다 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번만 실행되었습니다! 즉, 내가 설치한 Java 머신이 메소드를 호출하기로 결정한 경우는 27개 중 1개뿐이었습니다 finalize(). 다른 경우에는 메소드 없이 가비지 수집이 진행되었습니다. 이 코드를 직접 실행해 보세요. 결과가 다를 가능성이 높습니다. 보시다시피 신뢰할 수 있는 파트너라고 부르기는 어렵습니다 :) 따라서 미래를 위한 약간의 조언: 일부 중요한 리소스를 확보하는 경우 finalize()해당 방법에 의존해서는 안됩니다 . finalize()JVM이 이를 호출할 수도 있고 그렇지 않을 수도 있습니다. 누가 알아? 수명 동안 개체가 성능에 매우 중요한 일부 리소스를 점유한 경우(예: 데이터베이스에 대한 열린 연결을 유지) 클래스에서 특수 메서드를 생성하여 해당 개체를 해제하고 개체가 활성화될 때 명시적으로 호출하는 것이 좋습니다. 더 이상 필요 없어요. 이렇게 하면 프로그램 성능이 저하되지 않는다는 것을 확실히 알 수 있습니다. 맨 처음에 우리는 메모리 관리와 가비지 제거가 매우 중요하다고 말했는데 이는 사실입니다. 리소스를 부적절하게 처리하고 불필요한 객체를 조립하는 과정에 대한 이해가 부족하면 메모리 누수가 발생할 수 있습니다. 이것은 가장 유명한 프로그래밍 실수 중 하나입니다. 프로그래머가 잘못 작성한 코드로 인해 새로 생성된 개체에 대해 매번 새 메모리가 할당될 수 있으며, 오래되고 불필요한 개체는 가비지 수집기가 제거할 수 없습니다. 로봇청소기에 비유를 했으니, 로봇을 작동시키기 전에 양말을 집 여기저기에 흩뿌리고, 유리병을 깨뜨리고, 분해된 레고 세트를 바닥에 놔둔다면 어떤 일이 벌어질지 상상해 보세요. 물론 로봇은 무언가를 하려고 시도하지만 어느 시점에서는 멈춰버릴 것입니다.
객체 수명주기 - 3
제대로 작동하려면 바닥을 양호한 상태로 유지하고 진공청소기가 처리할 수 없는 모든 것을 제거해야 합니다. 가비지 수집기는 동일한 원리로 작동합니다. 프로그램에 수집할 수 없는 개체(양말이나 로봇 청소기의 레고 등)가 많이 남아 있으면 어느 시점에서 메모리가 부족해집니다. 그리고 작성한 프로그램뿐만 아니라 그 순간 컴퓨터에서 실행 중인 다른 모든 프로그램도 정지됩니다. 그들에게도 메모리가 충분하지 않습니다. 이것이 Java의 객체 수명주기와 가비지 수집기의 모습입니다. 이것을 외울 필요는 없습니다. 작동 원리만 이해하면 됩니다. 다음 강의에서는 이러한 프로세스에 대해 더 자세히 설명하겠지만 지금은 JavaRush 문제 해결로 돌아갈 수 있습니다 :) 행운을 빕니다!
코멘트
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION