์๋
! ์ค๋ ํ ๋ก ์์๋ Java์ "ํฌํ
์ฐธ์กฐ"(PhantomReference)์ ๋ํด ์์ธํ ์ด์ผ๊ธฐํ๊ฒ ์ต๋๋ค. ์ด๋ค์ ์ด๋ค ์ข
๋ฅ์ ์ฐธ์กฐ์
๋๊น? "์ ๋ น ์ฐธ์กฐ"๋ผ๊ณ ํ๋ ์ด์ ๋ ๋ฌด์์
๋๊น? ๊ทธ๋ค์ ์ด๋ป๊ฒ ์ฌ์ฉ๋ฉ๋๊น? ๊ธฐ์ตํ์๊ฒ ์ง๋ง Java์๋ 4๊ฐ์ง ์ข
๋ฅ์ ์ฐธ์กฐ๊ฐ ์์ต๋๋ค.
-
StrongReference (๊ฐ์ฒด๋ฅผ ์์ฑํ ๋ ์์ฑํ๋ ์ผ๋ฐ ์ฐธ์กฐ):
Cat cat = new Cat()
์ด ์์์ cat์ ๊ฐ๋ ฅํ ์ฐธ์กฐ์ ๋๋ค.
-
SoftReference (์ํํธ ์ฐธ์กฐ). ์ฐ๋ฆฌ๋ ๊ทธ๋ฌํ ์ฐธ์กฐ์ ๋ํ ๊ตํ์ ์ป์์ต๋๋ค.
-
WeakReference (์ฝํ ์ฐธ์กฐ). ์ฌ๊ธฐ์ ๋ํ ๊ตํ๋ ์์์ต๋๋ค .
-
PhantomReference (ํฌํ ์ฐธ์กฐ).
-
get() โ ์ฐธ์กฐ๋ ๊ฐ์ฒด๋ฅผ ๋ฐํํฉ๋๋ค.
- clear() โ ๊ฐ์ฒด์ ๋ํ ์ฐธ์กฐ๋ฅผ ์ ๊ฑฐํฉ๋๋ค.
finalize()
๋ฉ์๋๊ฐ ๊ฐ์ฒด์ ๋ํด ์ฌ์ ์๋ ๊ฒฝ์ฐ ํธ์ถ๋ฉ๋๋ค. ๋๋ ํธ์ถ๋์ง ์์์ ์๋ ์์ต๋๋ค. ๋ชจ๋ ์ด์ด ์ข์์ง ์ฌ๋ถ์ ๋ฌ๋ ค ์์ต๋๋ค. ๋ณ๋์ค๋ฝ๋ค๋ ๊ฒ์ ๊ธฐ์ตํ์ค ๊ฒ finalize()
์
๋๋ค :) ๊ฐ๋น์ง ์์ง๊ธฐ์ ๋ ๋ฒ์งธ ํจ์ค์์ ๊ฐ์ฒด๊ฐ ์ญ์ ๋๊ณ ๋ฉ๋ชจ๋ฆฌ๊ฐ ํด์ ๋ฉ๋๋ค. ๊ฐ๋น์ง ์์ง๊ธฐ์ ์์ธกํ ์ ์๋ ๋์์ ๋ง์ ๋ฌธ์ ๋ฅผ ์ผ๊ธฐํฉ๋๋ค. ๊ฐ๋น์ง ์ปฌ๋ ํฐ๊ฐ ์ธ์ ์คํ๋๊ธฐ ์์ํ ์ง๋ ์ ํํ ์ ์ ์์ต๋๋ค. finalize()
๋ฉ์๋๊ฐ ํธ์ถ๋๋์ง ์ฌ๋ถ๋ ์ ์ ์์ต๋๋ค . ๋ํ ๋ฉ์๋๊ฐ ์คํ๋๋ ๋์ ๊ฐ์ฒด์ ๋ํ ๊ฐ๋ ฅํ ์ฐธ์กฐ๊ฐ ์์ฑ๋ ์ ์์ผ๋ฉฐ finalize()
์ด ๊ฒฝ์ฐ ๊ฐ์ฒด๊ฐ ์ ํ ์ญ์ ๋์ง ์์ต๋๋ค. ์ฌ์ฉ ๊ฐ๋ฅํ ๋ฉ๋ชจ๋ฆฌ๋ฅผ ๋ง์ด ์๊ตฌํ๋ ํ๋ก๊ทธ๋จ์ ๊ฒฝ์ฐ ์ฝ๊ฒ OutOfMemoryError
. ์ด ๋ชจ๋ ๊ฒ์ด ํฌํ
์ฐธ์กฐ๋ฅผ ์ฌ์ฉํ๋๋ก ์ ๋ํฉ๋๋ค.. ์ฌ์ค ์ด๊ฒ์ ๊ฐ๋น์ง ์์ง๊ธฐ์ ๋์์ ๋ณ๊ฒฝํฉ๋๋ค. ๊ฐ์ฒด์ ํฌํ
์ฐธ์กฐ๋ง ์๋ ๊ฒฝ์ฐ:
-
finalize () ๋ฉ์๋๊ฐ ํธ์ถ๋ฉ๋๋ค(์ฌ์ ์๋ ๊ฒฝ์ฐ).
-
finalize() ๋ฉ์๋๊ฐ ์๋ฃ๋๊ณ ๊ฐ์ฒด๋ฅผ ์ฌ์ ํ ์ญ์ ํ ์ ์๋ ๊ฒฝ์ฐ ์๋ฌด ๊ฒ๋ ๋ณ๊ฒฝ๋์ง ์์ผ๋ฉด ๊ฐ์ฒด์ ๋ํ ํฌํ ์ฐธ์กฐ๊ฐ ํน์ ํ์ธ ReferenceQueue์ ๋ฐฐ์น ๋ฉ๋๋ค .
public class TestClass {
private StringBuffer data;
public TestClass() {
this.data = new StringBuffer();
for (long i = 0; i < 50000000; i++) {
this.data.append('x');
}
}
@Override
protected void finalize() {
System.out.println("The finalize method has been called on the TestClass object");
}
}
๊ฐ์ฒด๋ฅผ ๋ง๋ค ๋ ๋ ๋ง์ ๋ฉ๋ชจ๋ฆฌ๋ฅผ ์ฐจ์งํ๊ธฐ ์ํด ์๋์ ์ผ๋ก ๋ง๋ํ "๋ถํ"(๊ฐ ๊ฐ์ฒด์ 5์ฒ๋ง ๊ฐ์ "x" ๋ฌธ์๋ฅผ ์ถ๊ฐํ์ฌ)๋ฅผ ์ ๊ณตํฉ๋๋ค. ๋ํ finalize() ๋ฉ์๋๋ฅผ ์ฌ์ ์ํ์ฌ ์คํ๋๋์ง ํ์ธํฉ๋๋ค. ๋ค์์ผ๋ก PhantomReference ์์ ์์ํ ํด๋์ค๊ฐ ํ์ํฉ๋๋ค . ์ ๊ทธ๋ฐ ์์
์ด ํ์ํ๊ฐ์? ๋ชจ๋ ๊ฐ๋จํฉ๋๋ค. ์ด๋ ๊ฒ ํ๋ฉด ํฌํ
์ฐธ์กฐ๊ฐ ์ค์ ๋ก ์ง์์ก๋์ง(๊ฐ์ฒด๊ฐ ์ญ์ ๋์์์ ์๋ฏธ) ํ์ธํ๊ธฐ ์ํด clear() ๋ฉ์๋ ์ ์ถ๊ฐ ๋
ผ๋ฆฌ๋ฅผ ์ถ๊ฐํ ์ ์์ต๋๋ค .
import java.lang.ref.PhantomReference;
import java.lang.ref.ReferenceQueue;
public class MyPhantomReference<TestClass> extends PhantomReference<TestClass> {
public MyPhantomReference(TestClass obj, ReferenceQueue<TestClass> queue) {
super(obj, queue);
Thread thread = new QueueReadingThread<TestClass>(queue);
thread.start();
}
public void cleanup() {
System.out.println("Cleaning up a phantom reference! Removing an object from memory!");
clear();
}
}
๋ค์์ผ๋ก ๊ฐ๋น์ง ์์ง๊ธฐ๊ฐ ์์
์ ์ํํ ๋๊น์ง ๊ธฐ๋ค๋ฆด ๋ณ๋์ ์ค๋ ๋๊ฐ ํ์ํ๋ฉฐ ํฌํ
๋งํฌ๊ฐ ReferenceQueue์ ๋ํ ๋ฉ๋๋ค . ์ด๋ฌํ ์ฐธ์กฐ๊ฐ ๋๊ธฐ์ด์์ ๋๋๋ ์ฆ์ cleanup() ๋ฉ์๋๊ฐ ํธ์ถ๋ฉ๋๋ค.
import java.lang.ref.Reference;
import java.lang.ref.ReferenceQueue;
public class QueueReadingThread<TestClass> extends Thread {
private ReferenceQueue<TestClass> referenceQueue;
public QueueReadingThread(ReferenceQueue<TestClass> referenceQueue) {
this.referenceQueue = referenceQueue;
}
@Override
public void run() {
System.out.println("The thread monitoring the queue has started!");
Reference ref = null;
// Wait until the references appear in the queue
while ((ref = referenceQueue.poll()) == null) {
try {
Thread.sleep(50);
}
catch (InterruptedException e) {
throw new RuntimeException("Thread " + getName() + " was interrupted!");
}
}
// As soon as a phantom reference appears in the queue, clean it up
((MyPhantomReference) ref).cleanup();
}
}
๋ง์ง๋ง์ผ๋ก main() ๋ฉ์๋๊ฐ ํ์ํ๋ฉฐ ์ด๋ฅผ ๋ณ๋์ Main ํด๋์ค ์ ๋ฃ์ต๋๋ค . ์ด ๋ฉ์๋์์ ์ฐ๋ฆฌ๋ TestClass ๊ฐ์ฒด, ์ด์ ๋ํ ํฌํ
์ฐธ์กฐ ๋ฐ ํฌํ
์ฐธ์กฐ๋ฅผ ์ํ ํ๋ฅผ ๋ง๋ญ๋๋ค . ๊ทธ๋ฐ ๋ค์ ๊ฐ๋น์ง ์์ง๊ธฐ๋ฅผ ํธ์ถํ๊ณ ์ด๋ค ์ผ์ด ๋ฐ์ํ๋์ง ํ์ธํฉ๋๋ค. :)
import java.lang.ref.*;
public class Main {
public static void main(String[] args) throws InterruptedException {
Thread.sleep(10000);
ReferenceQueue<TestClass> queue = new ReferenceQueue<>();
Reference ref = new MyPhantomReference<>(new TestClass(), queue);
System.out.println("ref = " + ref);
Thread.sleep(5000);
System.out.println("Collecting garbage!");
System.gc();
Thread.sleep(300);
System.out.println("ref = " + ref);
Thread.sleep(5000);
System.out.println("Collecting garbage!");
System.gc();
}
}
์ฝ์ ์ถ๋ ฅ:
ref = MyPhantomReference@4554617c
The thread monitoring the queue has started!
Collecting garbage!
The finalize method has been called on the TestClass object
ref = MyPhantomReference@4554617c
Collecting garbage!
Cleaning up a phantom reference!
Removing an object from memory!
์ฌ๊ธฐ์ ๋ฌด์์ ๋ณผ ์ ์์ต๋๊น? ์ฐ๋ฆฌ๊ฐ ๊ณํํ๋๋ก ๋ชจ๋ ์ผ์ด ์ผ์ด๋ฌ์ต๋๋ค! ๊ฐ์ฒด์ finalize() ๋ฉ์๋๊ฐ ์ฌ์ ์๋์์ผ๋ฉฐ ๊ฐ๋น์ง ์์ง๊ธฐ๊ฐ ์คํ๋๋ ๋์ ํธ์ถ๋์์ต๋๋ค. ๋ค์์ผ๋ก ํฌํ
์ฐธ์กฐ๋ฅผ ReferenceQueue์ ๋ฃ์ ์ต๋๋ค . ๊ฑฐ๊ธฐ์ ์๋ ๋์ clear() ๋ฉ์๋๊ฐ ํธ์ถ๋์์ต๋๋ค(์ฐ๋ฆฌ๋ ์ฝ์์ ์ถ๋ ฅํ๊ธฐ ์ํด cleanup()์ ํธ์ถํ์ต๋๋ค). ๋ง์ง๋ง์ผ๋ก ๊ฐ์ฒด๊ฐ ๋ฉ๋ชจ๋ฆฌ์์ ์ญ์ ๋์์ต๋๋ค. ์ด์ ์ด๊ฒ์ด ์ด๋ป๊ฒ ์๋ํ๋์ง ์ ํํ ์ ์ ์์ต๋๋ค :) ๋ฌผ๋ก ํฌํ
์ฐธ์กฐ์ ๋ํ ๋ชจ๋ ์ด๋ก ์ ์๊ธฐํ ํ์๋ ์์ต๋๋ค. ํ์ง๋ง ์ ์ด๋ ์์ ๋ง ๊ธฐ์ตํ๋ค๋ฉด ์ข์ ๊ฒ์ด๋ค. ์ฒซ์งธ, ์ด๋ค์ ๊ฐ์ฅ ์ฝํ ์ฐธ์กฐ์
๋๋ค. ๊ฐ์ฒด์ ๋ํ ๋ค๋ฅธ ์ฐธ์กฐ๊ฐ ๋จ์ ์์ง ์์ ๊ฒฝ์ฐ์๋ง ์๋ํฉ๋๋ค. ์์์ ์ ๊ณตํ ์ฐธ์กฐ ๋ชฉ๋ก์ ๊ฐ์ฅ ๊ฐํ ๊ฒ๋ถํฐ ๊ฐ์ฅ ์ฝํ ๊ฒ๊น์ง ๋ด๋ฆผ์ฐจ์์ผ๋ก ์ ๋ ฌ๋ฉ๋๋ค. StrongReference -> SoftReference -> WeakReference -> PhantomReference ํฌํ
์ฐธ์กฐ๋ ๊ฐ์ฒด์ ๋ํ ๊ฐํ๊ฑฐ๋ ์ฝํ๊ฑฐ๋ ์ฝํ ์ฐธ์กฐ๊ฐ ์์ ๋๋ง ์ ํฌ์ ๋ค์ด๊ฐ๋๋ค. ) ๋์งธ, get() ๋ฉ์๋๋ ํฌํ
์ฐธ์กฐ์ ๋ํด ํญ์ null์ ๋ฐํํฉ๋๋ค. ๋ค์์ ์ธ ๊ฐ์ง ์ ํ์ ์๋์ฐจ์ ๋ํด ์ธ ๊ฐ์ง ์ ํ์ ์ฐธ์กฐ๋ฅผ ๋ง๋๋ ๊ฐ๋จํ ์์
๋๋ค.
import java.lang.ref.PhantomReference;
import java.lang.ref.ReferenceQueue;
import java.lang.ref.SoftReference;
import java.lang.ref.WeakReference;
public class Main {
public static void main(String[] args) {
Sedan sedan = new Sedan();
HybridAuto hybrid = new HybridAuto();
F1Car f1car = new F1Car();
SoftReference<Sedan> softReference = new SoftReference<>(sedan);
System.out.println(softReference.get());
WeakReference<HybridAuto> weakReference = new WeakReference<>(hybrid);
System.out.println(weakReference.get());
ReferenceQueue<F1Car> referenceQueue = new ReferenceQueue<>();
PhantomReference<F1Car> phantomReference = new PhantomReference<>(f1car, referenceQueue);
System.out.println(phantomReference.get());
}
}
์ฝ์ ์ถ๋ ฅ:
Sedan@4554617c
HybridAuto@74a14482
null
get () ๋ฉ์๋๋ ์ํํธ ์ฐธ์กฐ์ ์ฝํ ์ฐธ์กฐ์ ๋ํด ์์ ํ ์ผ๋ฐ ๊ฐ์ฒด๋ฅผ ๋ฐํํ์ง๋ง ํฌํ
์ฐธ์กฐ์ ๋ํด์๋ null์ ๋ฐํํ์ต๋๋ค. ์
์งธ, ํฌํ
์ฐธ์กฐ๋ ์ฃผ๋ก ๋ฉ๋ชจ๋ฆฌ์์ ๊ฐ์ฒด๋ฅผ ์ญ์ ํ๋ ๋ณต์กํ ์ ์ฐจ์ ์ฌ์ฉ๋ฉ๋๋ค. ๊ทธ๊ฒ ๋ค์ผ! :) ์ด๊ฒ์ผ๋ก ์ค๋ ์์
์ ๋ง์นฉ๋๋ค. ๊ทธ๋ฌ๋ ์ด๋ก ๋ง์ผ๋ก๋ ๋ฉ๋ฆฌ ๊ฐ ์ ์์ผ๋ฏ๋ก ๋ฌธ์ ํด๊ฒฐ๋ก ๋์๊ฐ ๋์
๋๋ค! :)
GO TO FULL VERSION