import java.lang.ref.PhantomReference;
import java.lang.ref.Reference;
import java.lang.ref.ReferenceQueue;
public class RessurectDemo {
private A a;
public static class A {
private RessurectDemo demo;
private String data;
public String getData() {
return data;
}
public A(RessurectDemo demo) {
this.demo = demo;
System.out.println("->заполняем объект информацией, съедаем ~400 МЬ памяти (смотрим в диспетчере задач)");
StringBuffer buff = new StringBuffer();
for (long i = 0; i < 50000000; i++) {
buff.append('a');
}
this.data = buff.toString();
System.out.println("<-заполнили объект информацией");
}
@Override
protected void finalize() throws Throwable {
System.out.println("в этом месте мог быть вызов у объекта метода *.finalize()");
}
}
private static class MyPhantomReference<T> extends PhantomReference<T> {
public MyPhantomReference(T obj, ReferenceQueue<? super T> queue) {
super(obj, queue);
Thread thread = new MyPollingThread<T>(queue);
thread.start();
}
public void cleanup() {
System.out.println("очищаем фантомную ссылку");
System.out.println("ждем, когда после очередного System.gc() освободятся 400 МЬ, занятые объектом");
clear();
}
public static class MyPollingThread<T> extends Thread {
private ReferenceQueue<? super T> referenceQueue;
public MyPollingThread(ReferenceQueue<? super T> referenceQueue) {
this.referenceQueue = referenceQueue;
}
@Override
public void run() {
System.out.println("запускаем процесс очистки очереди фантомных ссылок");
Reference<?> ref = null;
while ((ref = referenceQueue.poll()) == null) {
try {
Thread.sleep(50);
} catch (InterruptedException e) {
throw new RuntimeException("Thread " + getName() + " has been interrupted");
}
}
if (ref instanceof MyPhantomReference<?>) {
System.out.println("нашли фант.ссылку в очереди = "+ ref);
System.out.println("решаем,что делать с ссылкой (убиваем)");
((MyPhantomReference<?>) ref).cleanup();
}
}
}
}
public static void main(String[] args) throws InterruptedException {
RessurectDemo demo = new RessurectDemo();
Thread.sleep(20000);
Reference<A> ref = new MyPhantomReference<RessurectDemo.A>(new A(demo), new ReferenceQueue<RessurectDemo.A>());
System.out.println("создали фант.ссылку на объект = " + ref);
System.out.println("при этом объект из фант.ссылки = " + ref.get());
int count = 0;
for (int i = 0;i<20;i++){
Thread.sleep(10000);
System.out.println("вызываем System.gc(): "+ ++count);
System.gc();
}
System.out.println("программа закончилась");
}
}
Евгений Буш
35 уровень
Почему не умирает фантом? В чем изъян программы?
Комментарии (5)
- популярные
- новые
- старые
Для того, чтобы оставить комментарий Вы должны авторизоваться
Евгений Буш Программист в Компания Expert
28 марта 2020, 11:38
Так я и не могу добиться, чтобы 400 мб освободились. Объект продолжает занимать память до самого конца программы. Почему?!
0
Alexander Kornev
18 апреля 2020, 17:13
У меня занимается чуть более 200Мб. После первого GC вызывается finalize, после второго все очищается, остается около 30Мб, а после третьего видимо окончательно все подчищается и остается 20Мб. Вроде норм работает
0
Евгений Буш Программист в Компания Expert
18 апреля 2020, 20:55
этот код или другой аналогичный?
0
Alexander Kornev
20 апреля 2020, 15:23
этот код
проверил еще раз
0
Евгений Буш Программист в Компания Expert
20 апреля 2020, 21:07
ладно, спасибо. У меня эффект был нулевой, думал в коде дыра.
0