Question

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 TimerTasks, 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.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

Was it helpful?

Solution

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.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top