>  기사  >  Java  >  Java 객체 파괴 및 finalize 메소드 사용

Java 객체 파괴 및 finalize 메소드 사용

WBOY
WBOY앞으로
2022-07-28 15:31:031612검색

이 기사는 java에 대한 관련 지식을 제공합니다. 주로 Java의 객체 파괴 및 마무리 방법을 소개합니다. 모두에게 도움이 되기를 바랍니다.

Java 객체 파괴 및 finalize 메소드 사용

추천 학습: "java 비디오 튜토리얼"

객체 파괴

C++에서 소멸자 메소드는 리소스를 해제하고 객체 자체를 파괴하는 데 사용됩니다.

Java에서는 GC가 있기 때문에 메모리를 수동으로 회수할 필요가 없으므로 작업 부하가 크게 줄어들고 프로그램의 안전성이 향상됩니다. 그러나 Java에는 C++의 소멸자와 유사한 기능이 있습니다.

finalize 메소드

클래스가 GC에 의해 재활용될 때 일부 작업을 수행하려면 이 메소드를 오버로드하세요.

다음은 finalize를 구현한 클래스의 예시입니다.

Aoo 클래스에는 int 및 String 속성이 있으며 toString을 오버로드하고 생성 시 객체와 생성 시간을 인쇄하고 finalize에서 객체와 호출 시간을 인쇄합니다.

Aoo 클래스

public class Aoo {
       private int id;
       private String name;

       public Aoo(){
              this(0, null);
       }

       public Aoo(int id, String name){
              this.id = id;
              this.name = name;
              System.out.println(this.toString() + " now create:" + System.currentTimeMillis());
       }
        /*
        * 省略get/set/toString
        */
       protected void finalize() throws Throwable{
              super.finalize();
              System.out.println(this.toString() + "now finalize:" + System.currentTimeMillis());
       }
}

먼저 간단한 테스트

main method

public class FinalizeTest {
       public static void main(String[] args) throws Exception {
              Aoo a = new Aoo(1, "a");
              a = null;
              System.gc()
              Thread.sleep(2000);
              System.exit(0);
       }
}

인쇄 결과:

id:1 name:a now create:1497547723036
id:1 name:anow finalize:149754 7724059

객체의 GC 재활용

여기서는 GC를 수동으로 호출하여 메모리를 정리하고 System.gc();를 주석 처리하면 인쇄된 결과는 다음과 같습니다.

id:1 name:a now create: 1497547846923

즉, 특별히 GC를 호출하지 않으면 finalize 메소드가 전혀 호출되지 않습니다. 이는 이 객체가 전혀 적극적으로 재활용되지 않는다는 것을 의미합니다.

상상과는 달리 GC의 작동 모드는 게으르다. 즉, 메모리에 공간이 없으면 GC는 객체를 적극적으로 재활용하지 않습니다. 이 아이디어를 확인하기 위해 지속적으로 메모리를 소비하는 스레드를 만들었습니다. 적극적으로 GC를 호출하지 않습니다.

ThreadA 클래스

public class ThreadA implements Runnable{
       public void run() {
              List<Integer> list = new ArrayList<Integer>();
              int i = 0;
              while(true){
                     list.add(i);
                     i++;
              }
       }
}

main method

public class FinalizeTest {
       public static void main(String[] args) throws Exception {
              Aoo a = new Aoo(1, "a");
              a = null;
              ThreadA ta = new ThreadA();
              Thread t = new Thread(ta);
              t.start();
              Thread.sleep(2000);
              System.exit(0);
       }
}

인쇄 결과:

id:1 name:a now create:1497548135268
id:1 name:anow finalize:1497548135386

설명서는 없지만 이번에는 GC가 호출되었지만 finalize 메서드는 여전히 실행 중입니다. 즉, GC는 메모리가 소비되고 GC가 메모리를 정리해야 하는 경우에만 실행됩니다.

이러한 finalize 메서드는 호출할 수 있는지조차 확실하지 않으며 특정 작업을 완료해야 하는 경우에는 메서드를 수동으로 호출하거나 통합하는 것이 좋습니다. 마지막 블록에서 리소스를 해제합니다.

finalize 메서드에서 GC에 의해 재활용되는 것을 피하기 위해 참조를 자신에게 다시 할당해야 합니까?

GC 재활용을 방지하기 위해 finalize 메소드에서 재참조를 시도하세요

수정된 Aoo는 다음과 같습니다

public class Aoo {
       public static Aoo SAVE = null;
       private int id;
       private String name;

       public Aoo(){
              this(0, null);
       }

       public Aoo(int id, String name){
              this.id = id;
              this.name = name;
              System.out.println(this.toString() + " now create:" + System.currentTimeMillis());
       }  
       /*
        * 省略get/set/toString
        */
       protected void finalize() throws Throwable{
              super.finalize();
              System.out.println(this.toString() + "now finalize:" + System.currentTimeMillis());
              SAVE = this;
       }
}

main 메소드

public class FinalizeTest {
       public static void main(String[] args) throws Exception {
              Aoo.SAVE = new Aoo(1, "a");
              Aoo.SAVE = null;
              System.gc();
              Thread.sleep(500);
              System.out.println(Aoo.SAVE == null? "a is dead" : "a is alive" );              
              System.exit(0);             
       }
}

인쇄 결과:

id:1 name:a now create :1497551409195
id:1 name:anow finalize:1497551409201
a is Alive

여기서 Aoo.SAVE 객체가 실제로 "부활"된 것을 볼 수 있지만, 동일한 트릭을 반복하면 이러한 작업이 제한됩니다. 개체는 다시 "부활"되지 않습니다.

Main 메소드 re

public class FinalizeTest {
       public static void main(String[] args) throws Exception {
              Aoo.SAVE = new Aoo(1, "a");
              Aoo.SAVE = null;
              System.gc();
              Thread.sleep(500);
              System.out.println(Aoo.SAVE == null? "a is dead" : "a is alive" );

              Aoo.SAVE = null;
              System.gc();
              Thread.sleep(500);
              System.out.println(Aoo.SAVE == null? "a is dead" : "a is alive" );

              System.exit(0);          
       }
}
E

인쇄 결과:

id: 1 name: a now create: 1497551587715

ID: 1 name: any 두 작업은 동일하며 finalize 메소드는 다음에 의해 한 번만 호출됩니다. 체계.

finalze 메소드에서 무한 루프가 발생하면 어떻게 되나요?

Aoo 클래스

public class Aoo {
       private int id;
       private String name;

       public Aoo(){
              this(0, null);
       }

       public Aoo(int id, String name){
              this.id = id;
              this.name = name;
              System.out.println(this.toString() + " now create:" + System.currentTimeMillis());
       }
       /*
        * 省略get/set/toString
        */
       protected void finalize() throws Throwable{
              super.finalize();
              while(true){
                     System.out.println(this.toString() + "now finalize:" + System.currentTimeMillis());
                     Thread.sleep(100);
              }
       }
}

main method

public class FinalizeTest {
       public static void main(String[] args) throws Exception {
              Aoo a1 = new Aoo(1 , "a1");
              Aoo a2 = new Aoo(2 , "a2");
              a1 = null;
              a2 = null;
              ThreadA ta = new ThreadA();
              Thread t = new Thread(ta);
              t.start();
              Thread.sleep(5000);

              System.exit(0);
       }
}
인쇄 결과:

id:1 이름:a1 지금 생성:1497552024252id:2 이름:a2 지금 생성:1497552024252

id : 1 이름:a1now finalize:1497552024373

id:1 이름:a1now finalize:1497552024503

id:1 이름:a1now finalize:1497552026848
id:1 이름:a1now finalize:1497552028960

id:1 이름:a1now finalize:14975520 32363


결과는 무작위, 때로는 a1의 종료가 실행되고 때로는 a2의 종료가 실행됩니다.


이 결과는 두 가지 점을 보여줍니다.

1. finalze 방법의 스레드 우선순위는 매우 낮으며 시간 간격은 매우 불확실하며 분명히 100밀리초보다 큽니다.

2. 이 무한 루프로 인해 다른 개체의 finalize 메서드를 실행할 수 없습니다. 객체 생성에 이러한 무한 루프가 발생하면 객체가 파괴되지 않고 메모리 오버플로가 발생합니까?

우리는 다수의 Aoo 객체를 생성하고 GC가 스스로 메모리를 회수할 때까지 기다립니다.

finalize 메소드 호출을 시각적으로 관찰하기 위해 Aoo 객체가 초기화될 때 인쇄되는 코드를 삭제합니다.

main method

public class FinalizeTest {
       public static void main(String[] args) throws Exception {
              int i = 1;
              while(true){
                     Aoo a = new Aoo(i , "a" + i);
                     i++;
              }
       }
}

2분 정도 프로그램을 실행시킨 뒤, 수동으로 종료하고 출력을 확인해보세요

1497554225913
id:269614 이름:a269614now 마무리:1497554226151
id:269614 이름:a269614now 마무리:1497554227635
id:269614 이름:a269614now 마무리: 1497554227735
id:269614 이름:a269614now 완료:1497554227836
id:269614 이름:a269614now finalize:1497554229586
id:269614 name:a269614now finalize:1497554229686
id:269614 name:a269614now finalize:1497554229951
id:269614 name:a269614now finalize:149755 4230051
id:269614 이름:a269614now 완료:1497554230152
id:269614 이름:a269614now finalize:1497554233699
id:269614 name:a269614now finalize:1497554233800
id:269614 name:a269614now finalize:1497554233900
id:269614 name:a269614now finalize:149755 4234308
id:269614 이름:a269614now 완료:1497554234408
id:269614 이름:a269614now finalize:1497554234508
id:269614 name:a269614now finalize:1497554235053
id:269614 name:a269614now finalize:1497554235153
id:269614 name:a269614now finalize:149755 4235253
id:269614 이름:a269614now 완료:1497554235823
id:269614 이름:a269614now finalize:1497554235923
id:269614 name:a269614now finalize:1497554236023
id:269614 name:a269614now finalize:1497554240324
id:269614 name:a269614now finalize:149755 4240424
id:269614 이름:a269614now 완료:1497554240525
id:269614 이름:a269614now finalize:1497554241146
id:269614 name:a269614now finalize:1497554241247
id:269614 name:a269614now finalize:1497554241347
id:269614 name:a269614now finalize:149755 4241448
id:269614 이름:a269614now 완료:1497554242020
id:269614 이름:a269614now finalize:1497554242120
id:269614 name:a269614now finalize:1497554242220
id:269614 name:a269614now finalize:1497554242321
id:269614 name:a269614now finalize:149755 4242421
id:269614 이름:a269614now 완료:1497554242521
id:269614 이름:a269614now finalize:1497554248367
id:269614 name:a269614now finalize:1497554248467
id:269614 name:a269614now finalize:1497554248567
id:269614 name:a269614now finalize:149755 4248667
id:269614 이름:a269614now 완료:1497554249534
id:269614 이름:a269614now finalize:1497554249634
id:269614 name:a269614now finalize:1497554249734
id:269614 name:a269614now finalize:1497554249835
id:269614 name:a269614now finalize:149755 4255954
id:269614 이름:a269614now 완료:1497554256055
id:269614 이름:a269614now finalize:1497554256155
id:269614 name:a269614now finalize:1497554256255
id:269614 name:a269614now finalize:1497554256356
id:269614 name:a269614now finalize:149755 4257285
id:269614 이름:a269614now 완료:1497554257386
id:269614 이름:a269614now finalize:1497554257486
id:269614 name:a269614now finalize:1497554257586
id:269614 name:a269614now finalize:1497554257686
id:269614 name:a269614now finalize:149755 4268652
id:269614 이름:a269614now 완료:1497554268753
id:269614 이름:a269614now finalize:1497554268853
id:269614 name:a269614now finalize:1497554268953
id:269614 name:a269614now finalize:1497554269054
id:269614 name:a269614now finalize:149755 4269154
id:269614 이름:a269614now 완료:1497554277474
id:269614 이름:a269614now finalize:1497554292852
id:269614 name:a269614now finalize:1497554301062

可以发现两个情况:

1.只有一个对象최종 마무리 방법은 다음과 같습니다.对象执行finalize방식

2.程序执行很快的一段时间后,finalize방식은 就开始执行,但是随着内存消耗的不断增加,finalize방식대로次数也就越来越少。至于为什么这样,我不知道= =#

总结

至此, 우리는 finalize 방법을 사용하는 방법과 특별하게 정한 방법을 사용하지 않습니다. ,통통하지 않은 방법,了解了一些关于GC의 정보, 也让我明白,虽然Java语言虽然具유고도가 높은 一致性等点使之很容易上手, 但是要做到对Java의 精通,路还很远呢~~

推荐school习: 《java视频教程

위 내용은 Java 객체 파괴 및 finalize 메소드 사용의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
이 기사는 jb51.net에서 복제됩니다. 침해가 있는 경우 admin@php.cn으로 문의하시기 바랍니다. 삭제