2015-01-23 57 views
13

Khi tôi cố gắng ngăn chặn tomcat8 trên Java 8, tôi nhận được một vài bộ nhớ bị rò rỉ lỗi:nhớ Tomcat8 rò rỉ

org.apache.catalina.loader.WebappClassLoaderBase.clearReferencesThreads The web application [ROOT] appears to have started a thread named [Abandoned connection cleanup thread] but has failed to stop it. This is very likely to create a memory leak. Stack trace of thread: 
java.lang.Object.wait(Native Method) 
java.lang.ref.ReferenceQueue.remove(ReferenceQueue.java:142) 
com.mysql.jdbc.AbandonedConnectionCleanupThread.run(AbandonedConnectionCleanupThread.java:40) 
23-Jan-2015 08:18:10.202 WARNING [localhost-startStop-2] org.apache.catalina.loader.WebappClassLoaderBase.clearReferencesThreads The web application [ROOT] appears to have started a thread named [pool-5-thread-1] but has failed to stop it. This is very likely to create a memory leak. Stack trace of thread 


23-Jan-2015 08:18:10.205 SEVERE [localhost-startStop-2] org.apache.catalina.loader.WebappClassLoaderBase.checkThreadLocalMapForLeaks The web application [ROOT] created a ThreadLocal with key of type [com.util.ThreadLocalProperties$1] (value [[email protected]]) and a value of type [java.util.Properties] (value [{}]) but failed to remove it when the web application was stopped. Threads are going to be renewed over time to try and avoid a probable memory leak. 

Các ThreadLocalProperties lớp là:

public class ThreadLocalProperties extends Properties { 

    private static final long serialVersionUID = -4260632266508618756L; 
    private final ThreadLocal<Properties> localProperties = new ThreadLocal<Properties>() { 
     @Override 
     protected Properties initialValue() { 
      return new Properties(); 
     } 
    }; 

    public ThreadLocalProperties(Properties properties) { 
     super(properties); 
    } 

    @Override 
    public String getProperty(String key) { 
     String localValue = localProperties.get().getProperty(key); 
     return localValue == null ? super.getProperty(key) : localValue; 
    } 

    @Override 
    public Object setProperty(String key, String value) { 
     return localProperties.get().setProperty(key, value); 
    } 

    public ThreadLocal<Properties> getThreadLocal() { 
     return localProperties; 
    } 
} 

và tôi bắt đầu và ngăn chặn nó như này:

@WebListener() 
public class GeneralListener implements ServletContextListener { 

    ThreadLocalProperties threadLocalProperties = new ThreadLocalProperties(System.getProperties()); 

    @Override 
    public void contextDestroyed(ServletContextEvent arg0) { 
     threadLocalProperties.getThreadLocal().remove(); 
    } 

    @Override 
    public void contextInitialized(ServletContextEvent arg0) { 
     System.setProperties(threadLocalProperties); 
    } 
} 

Tại sao tôi nhận được tất cả bộ nhớ này bị lỗi? cũng như, khi tôi tắt máy, nó không tắt nó, tôi phải tự tay giết quá trình.

Điều gì là sai?

+0

http://docs.oracle.com/cd/E17952_01/connector-j-relnotes-en/news-5-1-23.html – David

Trả lời

9

Không có gì phải lo lắng. Đây là một kết quả đầu ra tomcat thông báo tiêu chuẩn khi phát hiện ứng dụng đã bắt đầu riêng của nó là Thread hoặc tạo một ThreadLocal. Nếu bạn chấm dứt chuỗi khi tắt máy và xóa threadlocals khi chúng không còn cần thiết, thì sẽ không có vấn đề gì.

Tại sao tôi nhận được tất cả bộ nhớ này bị lỗi? Đồng thời, khi tôi chạy tắt máy, nó không tắt nó, tôi phải tự hủy quy trình .

Tôi đã nhìn thấy hành vi này, khi một ứng dụng đã bắt đầu ScheduledExecutor (nhưng điều này sẽ xảy ra với bất kỳ khác Thread/TheadPool) và không đóng cửa trên contextDestroyed. Vì vậy, hãy kiểm tra xem bạn có đang tắt các luồng của mình khi dừng ứng dụng/máy chủ hay không.

Bây giờ vào vấn đề cụ thể của bạn tại sao máy chủ không chỉ dừng lại: trình điều khiển JDBC được đăng ký trong JVM như độc thân, và được chia sẻ với tất cả các ứng dụng web. Thông tin thêm here. Giải pháp tốt nhất cho vấn đề của bạn là di chuyển trình điều khiển MySQL trong thư mục /lib của Tomcat. Nếu bạn không thể làm điều đó bạn có thể thử this nhưng nó giống như một hack hơn là một giải pháp thực sự.

+0

Cảm ơn. Có nó thực sự đã giúp! điều thú vị là, nếu tôi triển khai ứng dụng của mình được gọi là Algo và có trong máy chủ này WEB-INF/web.xml nó sẽ triển khai Algo war cho cả thư mục Algo và thư mục ROOT! – Dejell

+2

Di chuyển trình điều khiển mysql vào thư mục Tomcat/lib không hoạt động đối với tôi. – Neets

+0

Bạn có xóa trình điều khiển khỏi/WEB-INF/lib không? Bạn sẽ nhận được thông báo này nếu ứng dụng của bạn đang bắt đầu chuỗi và không dừng chúng. –

1

Tôi nghĩ vấn đề của bạn tương tự như this. Khi bạn triển khai lại ứng dụng, apache triển khai nó theo từng bước, trong đó system.gc(); không hoạt động và sau vài lần triển khai lại trong giai đoạn phát triển, không gian được tạo vĩnh viễn sẽ đầy và bạn gặp lỗi rò rỉ bộ nhớ.

Vui lòng tiếp tục khởi động lại máy chủ của bạn sau vài lần triển khai lại, do đó, không gian PermGen có thể bị xóa khi khởi động lại.

Hoặc

bạn cũng có thể giải quyết bằng cách thay đổi khoảng trống PermGen trong máy chủ. Vui lòng truy cập here.

Tôi hy vọng điều này sẽ giúp bạn.

+0

Tôi không triển khai lại máy chủ. Tôi ./shutdown và ./startup nó. Tôi tin rằng nó xóa kích thước perm không? – Dejell

+0

Ngoài ra, khi tôi đã thử thêm định nghĩa kích thước perm để tomcat8 tôi nhận được một cảnh báo rằng nó đang bị bỏ qua – Dejell

+0

Bạn có lẽ cũng đang chạy Java 8? Tôi không chắc chắn 100%, nhưng tôi nghĩ rằng không gian permgen đã trở nên không thích hợp với bản phát hành đó.Tôi thấy không có lý do tại sao các thông điệp cảnh báo thông tin mà Tomcat đang khai thác có bất cứ điều gì để làm với không gian permgen, cũng không phải là họ bất cứ điều gì phải lo lắng về nếu bạn đang khó khởi động lại máy chủ. – Gimby