Tôi đang triển khai ServletContextListener để lên lịch cho các công việc khác nhau trên máy chủ ứng dụng của tôi (GlassFish 3.1). Tôi đang sử dụng contextInitialized()
để sắp xếp công việc lặp đi lặp lại, và contextDestroyed()
để gọi các phương thức dọn dẹp, chẳng hạn như tắt C3P0: logicInputStream mở trái từ cuộc gọi TimerTask tới bản đồ ổi; GlassFish than phiền về sự thất bại
public class JobScheduler implements ServletContextListener {
@Override
public void contextInitialized(ServletContextEvent sce) {
//schedule TimerTasks
}
@Override
public void contextDestroyed(ServletContextEvent sce) {
//cancel TimerTasks
//cleanup methods
}
}
Khi tôi hủy TimerTask
s, tôi đã nói thêm rằng chờ đợi bất kỳ tác vụ đang chạy để kết thúc trước tiếp tục, để đảm bảo không có gì vẫn đang thực hiện khi tôi dọn sạch tài nguyên.
Đến câu hỏi của tôi: khi tôi undeploy ứng dụng của tôi, tôi nhìn thấy một hoặc hai trong số những cảnh báo này được hiển thị trong kết quả GlassFish:
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)
Từ những gì tôi có thể nói, GlassFish là phàn nàn về một InputStream
không bao giờ được đóng kín một cách rõ ràng, được mở bởi một số ClassLoader
cho một số Finalizer
được gọi bằng một trong những bản đồ điện toán được tạo ra của tôi, được truy cập bởi tác vụ này. Lưu ý rằng dấu vết ngăn xếp ở trên không phải là ngoại lệ, mà là dấu vết thực tế từ tác vụ đang chạy đến quá trình khởi tạo của luồng.
Điều tôi cần trợ giúp là hiểu tại sao InputStream
này đang được mở ngay cả khi tôi đang chờ tất cả các tác vụ hoàn tất và tôi có thể xử lý tốt hơn việc dọn dẹp hay không. Nó dường như liên quan cụ thể đến các bản đồ điện toán của Guava mà bạn có thể thấy trong theo dõi ngăn xếp.
Cập nhật: tôi vẫn nhận được những lời cảnh báo tương tự nếu tôi sử dụng ScheduledThreadPoolExecutor
thay vì TimerTask
Cập nhật 2: Tumbleweeded
Mã của bạn nơi bạn quản lý công việc hẹn giờ như thế nào? –
Không có bất kỳ chi tiết nào về TimerTask đang làm gì, thật khó để đề xuất một giải pháp. Cụ thể, có bất kỳ Luồng, Ổ cắm hoặc Tệp nào mở theo tác vụ không? – hidralisk
@hidralisk - Hệ thống mã quá phức tạp để hiển thị ở đây. Như bạn có thể thấy mặc dù, stacktrace từ cảnh báo cho thấy cách các dòng được instantiated. –