I'm implementing ServletContextListener in order to schedule various jobs on my app server (GlassFish 3.1). I'm using contextInitialized()
to schedule recurring tasks, and contextDestroyed()
to call cleanup methods, such as shutting down c3p0:
public class JobScheduler implements ServletContextListener {
@Override
public void contextInitialized(ServletContextEvent sce) {
//schedule TimerTasks
}
@Override
public void contextDestroyed(ServletContextEvent sce) {
//cancel TimerTasks
//cleanup methods
}
}
When I cancel the TimerTask
s, I have added logic that waits for any running tasks to finish before continuing, to make sure nothing is still executing when I clean up resources.
Getting to my question: when I undeploy my application, I'm seeing one or two of these warnings being displayed in GlassFish output:
WARNING: Input stream has been finalized or forced closed without being explicitly closed; stream instantiation reported in following stack trace
java.lang.Throwable
at com.sun.enterprise.loader.ASURLClassLoader$SentinelInputStream.<init>(ASURLClassLoader.java:1230)
at com.sun.enterprise.loader.ASURLClassLoader$InternalJarURLConnection.getInputStream(ASURLClassLoader.java:1338)
at sun.misc.URLClassPath$Loader.getResource(URLClassPath.java:503)
at sun.misc.URLClassPath.getResource(URLClassPath.java:169)
at java.net.URLClassLoader$1.run(URLClassLoader.java:194)
at java.security.AccessController.doPrivileged(Native Method)
at java.net.URLClassLoader.findClass(URLClassLoader.java:190)
at java.lang.ClassLoader.loadClass(ClassLoader.java:307)
at java.lang.ClassLoader.loadClass(ClassLoader.java:248)
at com.google开发者_StackOverflow社区.common.base.FinalizableReferenceQueue$DecoupledLoader.loadFinalizer(FinalizableReferenceQueue.java:228)
at com.google.common.base.FinalizableReferenceQueue.loadFinalizer(FinalizableReferenceQueue.java:155)
at com.google.common.base.FinalizableReferenceQueue.<clinit>(FinalizableReferenceQueue.java:84)
at com.google.common.collect.CustomConcurrentHashMap$QueueHolder.<clinit>(CustomConcurrentHashMap.java:651)
at com.google.common.collect.CustomConcurrentHashMap$WeakValueReference.<init>(CustomConcurrentHashMap.java:1589)
at com.google.common.collect.CustomConcurrentHashMap$Strength$3.referenceValue(CustomConcurrentHashMap.java:322)
at com.google.common.collect.CustomConcurrentHashMap.newValueReference(CustomConcurrentHashMap.java:1731)
at com.google.common.collect.CustomConcurrentHashMap$Segment.setValue(CustomConcurrentHashMap.java:2050)
at com.google.common.collect.CustomConcurrentHashMap$Segment.put(CustomConcurrentHashMap.java:2430)
at com.google.common.collect.CustomConcurrentHashMap.put(CustomConcurrentHashMap.java:3346)
at MyProject.CacheEngine$MyCustomCache$1.apply(CacheEngine.java:244)
at MyProject.CacheEngine$MyCustomCache$1.apply(CacheEngine.java:237)
at com.google.common.collect.ComputingConcurrentHashMap$ComputingValueReference.compute(ComputingConcurrentHashMap.java:316)
at com.google.common.collect.ComputingConcurrentHashMap$ComputingSegment.compute(ComputingConcurrentHashMap.java:140)
at com.google.common.collect.ComputingConcurrentHashMap.apply(ComputingConcurrentHashMap.java:71)
at com.google.common.collect.MapMaker$ComputingMapAdapter.get(MapMaker.java:848)
//stacktrace of the Runnable called by TimerTask, leading up to a call to Guava ComputingMap
at java.util.TimerThread.mainLoop(Timer.java:512)
at java.util.TimerThread.run(Timer.java:462)
From what I can tell, GlassFish is complaining about an InputStream
that was never explicitly closed, which was opened by a ClassLoader
for a Finalizer
called by one of my Guava MapMaker
-created computing maps, which is being accessed by the task. Note that the stack trace above is not that of an exception, but the actual trace from the running task to the stream's instantiation.
What I need help with is understanding why this InputStream
is being left open even though I'm waiting for all tasks to finish, and whether or not I can better handle its cleanup. It seems to be specifically related to Guava's computing maps that you can see in the stack trace.
Update: I still get the same warnings if I use ScheduledThreadPoolExecutor
instead of TimerTask
Update 2: Tumbleweeded
Probably need to use a newer version of the library, the following is from the guava java docs:
FinalizableReferenceQueue() Deprecated.
FinalizableReferenceQueue is an unsound mechanism for cleaning up references, because (1) it's single thread can be easily overloaded, and (2) it's insistence on running a background thread is problematic in certain environments. This class is scheduled for deletion in December 2012.
精彩评论