Tôi có WebApplication được triển khai trong Tomcat 7.0.70. Tôi đã mô phỏng tình huống sau:Rò rỉ bộ nhớ khi triển khai lại ứng dụng trong Tomcat
- Tôi đã tạo vùng lưu trữ.
- Sau đó, tôi đã gửi yêu cầu Http và trong phương thức của dịch vụ, tôi đã in luồng hiện tại và trình nạp lớp của nó. Và sau đó tôi gọi Thread.currentThread.sleep (10000).
- Và tại cùng thời điểm tôi đã nhấp vào 'không triển khai ứng dụng này' trong trang quản trị của Tomcat.
- Tôi đã tạo kết xuất vùng heap mới.
- Sau một vài phút, tôi đã tạo ra bãi chứa hep mới.
KẾT QUẢ
Chủ đề bãi
Trên màn hình sau đây bạn có thể thấy rằng sau khi tôi nhấp vào "triển khai lại", tất cả các chủ đề (mà đã được liên kết với ứng dụng web này) đã bị giết trừ chuỗi "http-apr-8081-exec-10". Khi tôi đặt thuộc tính của Tomcat là "renewThreadsWhenStoppingContext == true", vì vậy bạn có thể thấy rằng sau một thời gian luồng này ("http-apr-8081-exec-10") đã bị giết và luồng mới (http-apr-8081-exec-11)) được tạo ra thay vì nó. Vì vậy, tôi đã không mong đợi để có WCL cũ sau khi tạo ra đống đống 3, bởi vì không có bất kỳ chủ đề cũ hoặc các đối tượng.
Heapd đổ 1
Trên hai màn hình sau đây bạn có thể thấy rằng khi ứng dụng đang chạy chỉ có một WCL (tham số của nó "bắt đầu" = true). Và chuỗi "http-apr-8081-exec-10" có contextClassLoader = URLClassLoader (vì nó nằm trong nhóm của Tomcat). Tôi chỉ nói về chủ đề này vì bạn có thể thấy rằng chuỗi này sẽ xử lý yêu cầu HTTP trong tương lai của tôi.
Gửi yêu cầu HTTP
Bây giờ tôi gửi yêu cầu HTTP và trong mã của tôi tôi nhận được thông tin về các thread.You hiện tại có thể thấy rằng yêu cầu của tôi là đang được xử lý theo chuỗi "http-apr-8081-exec-10"
дек 23, 2016 9:28:16 AM c.c.c.f.s.r.ReportGenerationServiceImpl INFO: request has been handled in
thread = http-apr-8081-exec-10, its contextClassLoader = WebappClassLoader
context: /hdi
delegate: false
repositories:
/WEB-INF/classes/
----------> Parent Classloader: [email protected]
Sau đó, tôi nhấp vào "Triển khai lại ứng dụng web của tôi" và tôi nhận được thông báo sau trong bảng điều khiển.
дек 23, 2016 9:28:27 AM org.apache.catalina.loader.WebappClassLoaderBase clearReferencesThreads
SEVERE: The web application [/hdi] appears to have started a thread named [http-apr-8081-exec-10] but has failed to stop it. This is very likely to create a memory leak.
Heapd đổ 2
Trên màn hình sau đây bạn có thể thấy rằng có hai trường hợp WebAppClassLoader. Một trong số đó (số # 1) là cũ (thuộc tính của nó "started" = false). Và WCL # 2 được tạo sau khi triển khai lại ứng dụng (thuộc tính của nó "started" = true). Và chuỗi chúng tôi xem xét có contextClassLoader = "org.apache.catalina.loader.WebappClassLoader". Tại sao? Tôi dự kiến sẽ thấy contextClassLoader = "java.net.URLClassLoader" (sau khi tất cả, khi bất kỳ thread nào kết thúc công việc của nó, nó được trả về hồ bơi của Tomcat và thuộc tính "contextClassLoader" được đặt thành bất kỳ trình nạp lớp cơ sở nào).
Heapd đổ 3
Bạn có thể thấy rằng có không phải là thread "http-Tháng tư-8081-exec-10", nhưng có chuỗi "http-apr-8081-exec-11" và nó có contextClassLoader = "WebappClassLoader" (Tại sao không phải URLClassLoader?).
Cuối cùng, chúng tôi có những điều sau đây: có chuỗi "http-apr-8081-exec-11" có tham chiếu đến WebappClassLoader # 1. Và obviosly khi tôi thực hiện "Root GC gần" trên WCL # 1 Tôi sẽ thấy những ref để thread 11.
câu hỏi.
Làm cách nào tôi có thể nói với Tomcat trả về giá trị cũ contextClassLoader (URLClassLoader) sau khi chuỗi sẽ kết thúc công việc?
Làm cách nào để đảm bảo Tomcat không sao chép giá trị cũ "contextClassLoader" trong quá trình gia hạn chuỗi?
Có thể, bạn có biết cách nào khác để giải quyết vấn đề của mình không?
Có thể trùng lặp của [Chủ đề trong Tomcat. Rò rỉ bộ nhớ] (http://stackoverflow.com/questions/41223141/threads-in-tomcat-memory-leaks) –
Nếu bạn không nhận được đủ sự chú ý lần đầu tiên, có lẽ bạn có thể bắt đầu một tiền thưởng. Không chỉ đăng lại cùng một câu hỏi. –
@ChristopherSchultz, bài đăng này cung cấp thêm thông tin. –