에서 finalize()
메소드가 호출되는 시기를 알아야 합니다 JVM
. finalize()
메서드를 재정 의하여 메서드를 호출 할 때 파일에 쓰는 테스트 클래스를 만들었 습니다. 실행되지 않습니다. 아무도 그것이 왜 실행되지 않는 이유를 말해 줄 수 있습니까?
답변
일반적으로 finalize()
청소 등을하지 않는 것이 가장 좋습니다 .
에 따르면 자바 독 (그것이 가치가 독서 것)이 있습니다 :
가비지 수집에서 객체에 대한 참조가 더 이상 없음을 확인할 때 객체의 가비지 수집기에 의해 호출됩니다.
Joachim이 지적했듯이, 객체에 항상 액세스 할 수 있다면 프로그램 수명 중에는 결코 일어날 수 없습니다.
또한 가비지 수집기는 특정 시간에 실행되도록 보장되지 않습니다. 일반적으로, 내가 말하려는 finalize()
것은 아마도 당신이 필요로하는 특별한 것이 없다면 일반적으로 사용하는 가장 좋은 방법은 아닐 것입니다.
답변
finalize
객체에 대한 쓰레기 수집 얻을 때 메서드가 호출됩니다. 가비지 수집 대상이 된 후 언제든지 가능합니다.
객체는 절대 가비지 수집 finalize
되지 않으므로 호출되지 않을 수도 있습니다. 이것은 객체가 gc를 사용할 수 없게 될 때 (JVM의 전체 수명 동안 도달 할 수 있기 때문에) 또는 객체가 적합한 시간과 JVM이 실행을 중지하는 시간 사이에 실제로 가비지 콜렉션이 실행되지 않는 경우에 발생할 수 있습니다 (이는 종종 단순하게 발생 함) 테스트 프로그램).
JVM finalize
에 아직 호출되지 않은 객체 에서 실행하도록 지시하는 방법이 있지만 사용하지 않는 것이 좋습니다 (해당 메소드의 보장도 그다지 강하지는 않습니다).
finalize
응용 프로그램의 올바른 작동에 의존 하면 문제가있는 것입니다. (일반적으로 Java 이외의) 자원을 정리할 때만finalize
사용해야 합니다. 그리고 그건 정확히 JVM이되지 보장 않기 때문에 과거의 어떤 객체에 호출됩니다.finalize
답변
protected void finalize() throws Throwable {}
- 모든 클래스는
finalize()
java.lang.Object 에서 메소드를 상속합니다.- 이 메소드는 객체에 대한 참조가 더 이상 없다고 판단되면 가비지 수집기에서 호출합니다.
- Object finalize 메서드는 동작을 수행하지 않지만 클래스에 의해 재정의 될 수 있습니다.
- 일반적으로 비 Java 자원을 정리 (예 : 파일 닫기)하도록 대체해야합니다.
재정의
finalize()
하는 경우 try-catch-finally 문을 사용하고 항상을 호출하는 것이super.finalize()
좋습니다. 이것은 클래스를 호출하는 객체가 사용하는 리소스를 실수로 놓치는 일이 없도록 안전 조치입니다.protected void finalize() throws Throwable { try { close(); // close open files } finally { super.finalize(); } }
finalize()
가비지 수집 중에 발생한 예외 는 종료를 중단하지만 그렇지 않으면 무시됩니다.finalize()
어떤 객체에서도 두 번 이상 실행되지 않습니다
인용 : http://www.janeg.ca/scjp/gc/finalize.html
이 기사를 확인할 수도 있습니다.
답변
Java finalize()
메소드는 소멸자가 아니며 애플리케이션이 의존하는 논리를 처리하는 데 사용해서는 안됩니다. Java 사양에 따르면 finalize
응용 프로그램을 실행하는 동안 메서드 가 전혀 호출 되지 않을 수도 있습니다.
아마도 당신이 원하는 것은 다음 finally
과 같이 정리 방법입니다.
MyClass myObj;
try {
myObj = new MyClass();
// ...
} finally {
if (null != myObj) {
myObj.cleanup();
}
}
답변
Effective Java, 2nd edition page 27을 확인하십시오.
항목 7 : 종료자를 피하십시오
종료자는 예측할 수없고 종종 위험하며 일반적으로 불필요합니다. 파이널 라이저에서 시간 결정적인 작업을 수행하지 마십시오. 중요한 영구 상태를 업데이트하기 위해 종료 자에 의존하지 마십시오.
리소스를 종료하려면 try-finally를 대신 사용하십시오.
// try-finally block guarantees execution of termination method Foo foo = new Foo(...); try { // Do what must be done with foo ... } finally { foo.terminate(); // Explicit termination method }
답변
finalize()
Java 에서 메소드 가 언제 호출됩니까?
finalize 메소드는 GC가 객체에 더 이상 도달 할 수 없음을 감지 한 후 객체가 사용한 메모리를 실제로 회수하기 전에 호출됩니다.
-
객체에 도달 할 수없는 경우
finalize()
절대로 호출되지 않습니다. -
GC가 실행되지 않으면
finalize()
호출되지 않을 수 있습니다. 일반적으로 GC는 JVM에서 가비지가 충분하다고 판단 할 때만 실행됩니다. -
GC가 특정 개체에 도달 할 수없는 것으로 판단하기 전에 두 개 이상의 GC주기가 필요할 수 있습니다. Java GC는 일반적으로 “세대”수집기입니다.
-
GC가 객체에 도달 할 수없고 최종화 할 수 있음을 감지하면 최종 큐에 배치됩니다. 마무리는 일반적으로 일반 GC와 비동기 적으로 발생합니다.
(JVM을 사양은 실제로 수 JVM을은에 결코 .이 오브젝트에 의해 사용되는 공간을 회수하지 않는 것을 제공 … 실행되지 파이 나라 쓸모 / 불구가 될 것이다 이런 식으로 구현 한 JVM을하지만,이 문제가 “허용”된다 .)
결말은 확정 된 시간 안에해야 할 일을 완수하기 위해 마무리에 의존하는 것이 현명하지 않다는 것입니다. 전혀 사용하지 않는 것이 “모범 사례”입니다. finalize()
메소드 에서 수행하려는 모든 작업을 수행하는 더 나은 (즉, 더 안정적인) 방법이 있어야합니다 .
마무리를 위해 합법적으로 사용하는 유일한 용도는 응용 프로그램 코드에서 손실 된 개체와 관련된 리소스를 정리하는 것입니다. 그럼에도 불구하고, 처음부터 객체를 잃지 않도록 애플리케이션 코드를 작성해야합니다. (예를 들어, Java 7+ try-with-resources 를 사용하여 close()
항상 호출되도록하십시오.)
finalize () 메서드를 재정 의하여 호출하면 파일에 쓰는 테스트 클래스를 만들었습니다. 실행되지 않습니다. 아무도 왜 그것이 실행되지 않는 이유를 말해 줄 수 있습니까?
말하기는 어렵지만 몇 가지 가능성이 있습니다.
- 개체는 여전히 접근 가능하므로 가비지 수집되지 않습니다.
- 테스트가 완료되기 전에 GC가 실행되지 않으므로 객체가 가비지 수집되지 않습니다.
- 개체가 GC에 의해 발견되어 GC에 의해 종료 큐에 배치되지만 테스트가 완료되기 전에 완료가 완료되지 않습니다.
답변
JVM이 finalize () 메소드를 호출 할 때 불확실성이 있기 때문에 (오버라이드 된 finalize ()가 실행되는지 여부를 확실하지 않음), 연구 목적으로 finalize ()가 호출 될 때 발생하는 것을 관찰하는 더 좋은 방법은 다음과 같습니다. JVM이 명령에 의해 가비지 콜렉션을 강제로 호출하도록합니다 System.gc()
.
특히 finalize ()는 객체를 더 이상 사용하지 않을 때 호출됩니다. 그러나 새 객체를 만들어 호출하려고 할 때 확실하게 호출 할 수 없습니다. 따라서 확실히 미래에 사용되지 않는 null
객체 c
를 생성하므로 객체 c
의 최종 호출을 볼 수 있습니다.
예
class Car {
int maxspeed;
Car() {
maxspeed = 70;
}
protected void finalize() {
// Originally finalize method does nothing, but here we override finalize() saying it to print some stmt
// Calling of finalize is uncertain. Difficult to observe so we force JVM to call it by System.gc(); GarbageCollection
System.out.println("Called finalize method in class Car...");
}
}
class Bike {
int maxspeed;
Bike() {
maxspeed = 50;
}
protected void finalize() {
System.out.println("Called finalize method in class Bike...");
}
}
class Example {
public static void main(String args[]) {
Car c = new Car();
c = null; // if c weren`t null JVM wouldn't be certain it's cleared or not, null means has no future use or no longer in use hence clears it
Bike b = new Bike();
System.gc(); // should clear c, but not b
for (b.maxspeed = 1; b.maxspeed <= 70; b.maxspeed++) {
System.out.print("\t" + b.maxspeed);
if (b.maxspeed > 50) {
System.out.println("Over Speed. Pls slow down.");
}
}
}
}
산출
Called finalize method in class Car...
1 2 3 4 5 6 7 8 9
10 11 12 13 14 15 16 17 18 19
20 21 22 23 24 25 26 27 28 29
30 31 32 33 34 35 36 37 38 39
40 41 42 43 44 45 46 47 48 49
50 51Over Speed. Pls slow down.
52Over Speed. Pls slow down.
53Over Speed. Pls slow down.
54Over Speed. Pls slow down.
55Over Speed. Pls slow down.
56Over Speed. Pls slow down.
57Over Speed. Pls slow down.
58Over Speed. Pls slow down.
59Over Speed. Pls slow down.
60Over Speed. Pls slow down.
61Over Speed. Pls slow down.
62Over Speed. Pls slow down.
63Over Speed. Pls slow down.
64Over Speed. Pls slow down.
65Over Speed. Pls slow down.
66Over Speed. Pls slow down.
67Over Speed. Pls slow down.
68Over Speed. Pls slow down.
69Over Speed. Pls slow down.
70Over Speed. Pls slow down.
주 – 최대 70까지 인쇄 한 후 프로그램에서 오브젝트 b를 사용하지 않은 후에도 “Bike 클래스의 호출 된 종료 메소드 …”가 인쇄되지 않으므로 JVM이 b를 지 울지 여부가 불확실합니다.