2011-07-29 17 views
6

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

+0

Mã của bạn nơi bạn quản lý công việc hẹn giờ như thế nào? –

+0

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

+0

@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. –

Trả lời

1

Có lẽ cần phải sử dụng một phiên bản mới hơn của thư viện, sau đây là từ các tài liệu ổi java:

FinalizableReferenceQueue() Deprecated. 

Finali zableReferenceQueue là một cơ chế không rõ ràng để làm sạch các tham chiếu, bởi vì (1) nó có thể dễ dàng bị quá tải, và (2) nó khăng khăng khi chạy một luồng nền là có vấn đề trong một số môi trường nhất định. Lớp học này được lên kế hoạch xóa vào tháng 12 năm 2012.

+0

Thật không may tôi không còn có quyền truy cập vào mã mà tôi có thể xác nhận điều này như là một sửa chữa, nhưng có vẻ như 'FinalizableReferenceQueue' có lẽ là vấn đề ở đây. Đánh dấu là đã được chấp nhận. –

Các vấn đề liên quan