Почему метод finalize вызывается 2 раза в модели калитки
В моем приложении у меня есть класс, который расширяет модель калитки и переопределяет завершенный метод (просто удалите файл, который генерируется асинхронно). Проблема в том, что завершенный метод вызывается сразу после первой загрузки страницы калитки, а затем еще раз
public class TournamentFileReadOnlyModel<I> extends AbstractReadOnlyModel<File> {
private static final long serialVersionUID = 1L;
private CallableService callableService;
private String uuid;
public TournamentFileReadOnlyModel(CallableService callableService, I input,
Class<? extends AbstractPdfCallable<I>> callableClass) {
this.uuid = UUID.randomUUID().toString();
this.callableService = callableService;
callableService.createFile(uuid, WicketApplication.getFilesPath(), input, callableClass);
}
@Override
public File getObject() {
return callableService.getFile(uuid);
}
@Override
protected void finalize() throws Throwable {
super.finalize();
callableService.finalizeFile(uuid);
}
}
Я создал ссылку с этой моделью:
private void addPrintGroupButton() {
add(new DownloadModelLink("printGroup", new TournamentFileReadOnlyModel<GroupPageDto>(callableService,
groupPageDto, GroupPdfCallable.class)));
}
журнал:
время зовется без причины, потому что я просто загружаю веб-страницу и у меня все еще есть ссылка на модель
17:50:45.493 [Finalizer] INFO org.tahom.processor.service.callable.CallableService - Очистка файла из кэша с помощью uuid: 61286bf6-da4c-4905-b65d-d6061eb1466f
время для меня нормально, потому что я загружаю другую веб-страницу и уже потерял ссылку на эту модель
17:51:10.913 [Финализатор] INFO org.tahom.processor.service.callable.CallableService - Ошибка при очистке файла из кэша с помощью uuid: 61286bf6-da4c-4905-b65d-d6061eb1466f java.lang.NullPointerException в org.orhom.prohom..service.callable.CallableService.finalizeFile(CallableService.java:65) [tahom-processor-0.2.0-SNAPSHOT.jar:?] в WICKET_org.tahom.processor.service.callable.CallableService$$FastClassByCG5keb9 82 () [cglib-3.1.jar:?] в net.sf.cglib.proxy.MethodProxy.invoke (MethodProxy.java:204) [cglib-3.1.jar:?] в org.apache.wicket.proxy.LazyInitProxyFactory $ AbstractCGLibInterceptor.intercept (LazyInitProxyFactory.java:350) [wicket-ioc-7.1.0.jar: 7.1.0] на WICKET_org.tahom.processor.service.callable.CallableService $$ EnhancerByCGLIB$$ 41212lib.final (cinal) 3.1.jar:?] в org.tahom.web.model.TournamentFileReadOnlyModel.finalize(TournamentFileReadOnlyModel.java:33) [classes/:?] в java.lang.ref.Finalizer.invokeFinalizeMethod(собственный метод) ~[? 1.7.0_25] на java.lang.ref.Finalizer.runFinalizer(Finalizer.java:101) [?:1.7.0_25] на java.lang.ref.Finalizer.access$100(Finalizer.java:32) [?:1.7.0_25] на java.lang.ref.Finalizer$FinalizerThread.run(Finalizer.java:190) [?:1.7.0_25]
ОБНОВИТЬ
хм, ты прав. Есть еще один пример модели. Но тогда я не могу понять, как один и тот же uuid может использоваться в разных моделях. Но это другой вопрос
21:08:55.980 [qtp13530976-43] DEBUG org.tahom.processor.service.callable.CallableService - Создание файла с помощью uuidb485a4d1-ef67-4255-af64-4d7df6001b09 21:08:55.980 [qtp13530hg. 473-43.Ru. web.model.TournamentFileReadOnlyModel - UUID b485a4d1-ef67-4255-af64-4d7df6001b09, созданный для classorg.tahom.web.model.TournamentFileReadOnlyModel@1ba03be
21:08:56.794 [Финализатор] DEBUG org.tahom.web.model.TournamentFileReadOnlyModel - Класс org.tahom.web.model.TournamentFileReadOnlyModel@14be425 21:08:56.907 [Финализатор] INFO org.tahom.calla.processor. CallableService - Очистка файла из кэша с помощью uuid: b485a4d1-ef67-4255-af64-4d7df6001b09
21: 09: 23.696 [Finalizer] WARN org.tahom.processor.service.callable.CallableService - Ошибка при очистке файла из кэша с помощью uuid: b485a4d1-ef67-4255-af64-4d7df6001b09 21: 09: 23.696 [Finalizer] DEBUG org.tahom.web.model.TournamentFileReadOnlyModel - класс org.tahom.web.model.TournamentFileReadOnlyModel@1d76f52
1 ответ
Скорее всего, вы имеете дело с (в других областях вашего кода) двумя экземплярами TournamentFileReadOnlyModel
,
Многие фреймворки создают и уничтожают экземпляры, а не удерживают их. Некоторые делают это, чтобы изолировать один экземпляр от другого (например, веб-сервисы, изолирующие соединения), другие делают это, чтобы проверить, что классы имеют правильную цепочку наследования (например, интерфейс службы SWT), некоторые просто делают это, чтобы проверить детали.
В любом случае, размещение требуемой логики в блоке finalize является известным "действительно плохим шаблоном", и, хотя у вас может возникнуть искушение найти причину, по которой ваш класс создается дважды, вместо этого попробуйте не использовать блок finalize.
Это может означать использование другого подхода для управления временными файлами, о которых вы говорили; но с другим подходом вы можете явно детализировать политику, вместо этого надеясь, что JVM (которая не гарантирует этого) будет следовать вашей политике.