Есть многопоточное приложение.
Один из методов создает экземпляр ScheduledExecutorService
.
После задает расписание и делает shutdown()
.
Далее через определенное время запускается код по расписанию (таких параллельных кодов может быть много, поскольку приложение многопоточное).
Здесь вопрос, когда GC удалит экземпляр ScheduledExecutorService
из памяти, после выполнения расписания?
Сборщик удаляет объекты тогда, когда на них нет ссылок. Я сделал дамп кучи после вызова метода ExecutorService.shutdown()
, но до выполнения запланированной задачи. Судя по нему, ссылок на экземпляр ScheduledExecutorService
множество:
Rootset references to java.util.concurrent.ScheduledThreadPoolExecutor@0x6c1209178 (excludes weak refs)
References to java.util.concurrent.ScheduledThreadPoolExecutor@0x6c1209178 (112 bytes)
Java Local References
Java Local Reference (from java.lang.Thread@0x6c1208f88) :
--> java.util.concurrent.ScheduledThreadPoolExecutor@0x6c1209178 (112 bytes)
Java Local Reference (from java.lang.Thread@0x6c1208f88) :
--> java.util.concurrent.ThreadPoolExecutor$Worker@0x6c12091c8 (76 bytes) (field this$0:)
--> java.util.concurrent.ScheduledThreadPoolExecutor@0x6c1209178 (112 bytes)
Java Local Reference (from java.lang.Thread@0x6c1208f88) :
--> java.lang.Thread@0x6c1208f88 (171 bytes) (field target:)
--> java.util.concurrent.ThreadPoolExecutor$Worker@0x6c12091c8 (76 bytes) (field this$0:)
--> java.util.concurrent.ScheduledThreadPoolExecutor@0x6c1209178 (112 bytes)
Java Local Reference (from java.lang.Thread@0x6c1208f88) :
--> java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue@0x6c1209148 (52 bytes) (field queue:)
--> [Ljava.util.concurrent.RunnableScheduledFuture;@0x6c123e000 (144 bytes) (Element 0 of [Ljava.util.concurrent.RunnableScheduledFuture;@0x6c123e000:)
--> java.util.concurrent.ScheduledThreadPoolExecutor$ScheduledFutureTask@0x6c123e050 (96 bytes) (field this$0:)
--> java.util.concurrent.ScheduledThreadPoolExecutor@0x6c1209178 (112 bytes)
Java Local Reference (from java.lang.Thread@0x6c1208f88) :
--> java.util.concurrent.locks.AbstractQueuedSynchronizer$Node@0x6c1209128 (52 bytes) (field thread:)
--> java.lang.Thread@0x6c1208f88 (171 bytes) (field target:)
--> java.util.concurrent.ThreadPoolExecutor$Worker@0x6c12091c8 (76 bytes) (field this$0:)
--> java.util.concurrent.ScheduledThreadPoolExecutor@0x6c1209178 (112 bytes)
Java Local Reference (from java.lang.Thread@0x6c1208f88) :
--> java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject@0x6c1209110 (40 bytes) (field lastWaiter:)
--> java.util.concurrent.locks.AbstractQueuedSynchronizer$Node@0x6c1209128 (52 bytes) (field thread:)
--> java.lang.Thread@0x6c1208f88 (171 bytes) (field target:)
--> java.util.concurrent.ThreadPoolExecutor$Worker@0x6c12091c8 (76 bytes) (field this$0:)
--> java.util.concurrent.ScheduledThreadPoolExecutor@0x6c1209178 (112 bytes)
Java Local Reference (from java.lang.ref.Reference$ReferenceHandler@0x6c1201de8) :
--> java.lang.ref.Reference$ReferenceHandler@0x6c1201de8 (171 bytes) (field group:)
--> java.lang.ThreadGroup@0x6c1201190 (67 bytes) (field groups:)
--> [Ljava.lang.ThreadGroup;@0x6c123dfc0 (48 bytes) (Element 0 of [Ljava.lang.ThreadGroup;@0x6c123dfc0:)
--> java.lang.ThreadGroup@0x6c1201160 (67 bytes) (field threads:)
--> [Ljava.lang.Thread;@0x6c123df30 (48 bytes) (Element 0 of [Ljava.lang.Thread;@0x6c123df30:)
--> java.lang.Thread@0x6c1208f88 (171 bytes) (field target:)
--> java.util.concurrent.ThreadPoolExecutor$Worker@0x6c12091c8 (76 bytes) (field this$0:)
--> java.util.concurrent.ScheduledThreadPoolExecutor@0x6c1209178 (112 bytes)
Java Local Reference (from java.lang.ref.Finalizer$FinalizerThread@0x6c1201c28) :
--> java.lang.ref.Finalizer$FinalizerThread@0x6c1201c28 (172 bytes) (field group:)
--> java.lang.ThreadGroup@0x6c1201190 (67 bytes) (field groups:)
--> [Ljava.lang.ThreadGroup;@0x6c123dfc0 (48 bytes) (Element 0 of [Ljava.lang.ThreadGroup;@0x6c123dfc0:)
--> java.lang.ThreadGroup@0x6c1201160 (67 bytes) (field threads:)
--> [Ljava.lang.Thread;@0x6c123df30 (48 bytes) (Element 0 of [Ljava.lang.Thread;@0x6c123df30:)
--> java.lang.Thread@0x6c1208f88 (171 bytes) (field target:)
--> java.util.concurrent.ThreadPoolExecutor$Worker@0x6c12091c8 (76 bytes) (field this$0:)
--> java.util.concurrent.ScheduledThreadPoolExecutor@0x6c1209178 (112 bytes)
Трасса у всех разная, но с одним корнем в нативном вызове Unsafe.park()
Stack Trace for Java Local Reference
sun.misc.Unsafe.park((ZJ)V) : Unsafe.java line (native method)
java.util.concurrent.locks.LockSupport.parkNanos((Ljava/lang/Object;J)V) : LockSupport.java line 215
java.util.concurrent.locks.AbstractQueuedSynchronizer$ConditionObject.awaitNanos((J)J) : AbstractQueuedSynchronizer.java line 2078
java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(()Ljava/util/concurrent/RunnableScheduledFuture;) : ScheduledThreadPoolExecutor.java line 1093
java.util.concurrent.ScheduledThreadPoolExecutor$DelayedWorkQueue.take(()Ljava/lang/Object;) : ScheduledThreadPoolExecutor.java line 809
java.util.concurrent.ThreadPoolExecutor.getTask(()Ljava/lang/Runnable;) : ThreadPoolExecutor.java line 1074
Конкретно из этой трассы видно, что поток заснул на вызове ThreadPoolExecutor.getTask()
, который удерживает кадр стека, в котором есть ссылка на экземпляр ScheduledExecutorService
, что в свою очередь не даёт удалить его сборщику мусора.
Айфон мало держит заряд, разбираемся с проблемой вместе с AppLab
Начал вникать в Docker и тут возник вопрос, возможно ли в Docker сделать так, чтобы он скачал проект с GitHub далее собрал его в War и положил в tomcat, далее...
На примере нахождения факториала хочется узнать насколько я правильно понимаю ООППредставим факториал как самостоятельную сущность:
Я использовал это для однообразного фона