2010-05-07 45 views
11
  • không java 6 tạo chủ đề bãi ngoài đống đổ (java_pid14941.hprof)làm thế nào để tạo ra chủ đề bãi java trên ra khỏi lỗi bộ nhớ

  • đây là những gì đã xảy ra với một trong những ứng dụng của tôi.

    java.lang.OutOfMemoryError: giới hạn overhead GC vượt đống bán phá giá để java_pid14941.hprof ...

  • tôi đã tìm ava_pid14941.hprof trong thư mục làm việc, nhưng không tìm thấy bất kỳ tập tin, trong đó có chủ đề bãi . Tôi cần phải biết tất cả các chủ đề đã làm gì khi tôi gặp lỗi OutOfMemory này.

  • Có tùy chọn cấu hình nào sẽ tạo kết xuất chuỗi ngoài vùng lưu trữ đống trên bộ nhớ ngoại lệ không?

Trả lời

14

How to generate thread dump java on out of memory error?

Câu hỏi của bạn có thể được đơn giản hóa thành:

  • làm thế nào để tạo ra một bãi chứa thread

và:

  • làm thế nào để nắm bắt một trong số lỗi bộ nhớ (don 't chú ý đến naysayer ở đây, họ đang thiếu hình ảnh lớn hơn, xem bình luận của tôi)

Vì vậy, nó thực sự khá dễ dàng, bạn có thể làm điều đó như thế này:

  • cài đặt một handler mặc định ngoại lệ uncaught

  • khi bắt một ngoại lệ còn tự do, kiểm tra xem bạn có một OutOfMemoryError

  • nếu bạn có lỗi OutOfMemoryError, hãy tự tạo một chuỗi kết xuất đầy đủ và yêu cầu người dùng gửi cho bạn qua email hoặc đề nghị gửi tự động

Phần thưởng: hoạt động tốt trên 1.5 quá :)

Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() { 
    public void uncaughtException(final Thread t, final Throwable e) { 
     ... 
    } 

Bạn có thể muốn xem xét điều này:

e.getMessage(); 

và điều này:

Thread.getAllStackTraces(); 

tôi đang làm điều này tất cả các thời gian trong một ứng dụng mà được vận chuyển trên hàng trăm JVM 1.5 và 1.6 khác nhau (trên các hệ điều hành khác nhau).

+5

Lưu ý rằng những người bình luận không biết gì có thể không có ý nghĩa như * "bạn không bao giờ bắt được OOM" * nhưng có lẽ họ chưa bao giờ làm việc trên các ứng dụng Java thực tế được triển khai trên hàng trăm hệ thống. Tôi làm điều này ** mọi lúc ** và ** nó chỉ hoạt động **. Điều này đã cho phép tôi gỡ lỗi từ xa và sửa chữa rất nhiều rò rỉ bộ nhớ rất tinh tế mà không bao giờ từng xuất hiện trong quá trình thử nghiệm. Nắm bắt một OOM ở đây có ý nghĩa hoàn hảo ** vì toàn bộ vấn đề là để hiểu tại sao OOM lại xảy ra **. Nhưng đừng ngạc nhiên khi thấy nhiều người dân ở đây không hiểu rằng ** thực tế rất cơ bản **. – SyntaxT3rr0r

+0

Dựa trên câu trả lời này, tôi tạo ra lớp tiện ích UncaughtExceptionLogger (http://pastebin.com/e30g9y66). Cái này bạn có thể định nghĩa, như là một bean Spring, và tất cả được thiết lập với việc ghi nhật ký mở rộng. – snowindy

0

Tôi không nghĩ có bất kỳ thứ gì trong java sẽ cung cấp cho bạn các bãi chứa luồng khi thoát. Tôi giải quyết điều này khi cần thiết bằng cách sử dụng cronjob có định kỳ kill -3 pid. Có, nó làm lộn xộn các bản ghi một chút, nhưng dấu chân vẫn còn không đáng kể.

Và nếu bạn đang bị OOM, có thể sẽ hữu ích khi xem tình hình phát triển theo chủ đề như thế nào.

+0

Tại sao lưu ý lại? – mindas

20

Nếu bạn đang ở trong một môi trường Linux/Unix bạn có thể làm điều này:

-XX:OnOutOfMemoryError="kill -3 pid" 

Bằng cách này bạn không cần phải có ứng dụng của bạn tạo ra bãi chủ đề định kỳ và bạn sẽ nhận được một bản chụp khi nó thực sự bị nghẹt thở.

+5

Trên thực tế, nó chỉ ra rằng bạn chỉ có thể tải Heap Dump của bạn được tạo ra trên OOME vào VisualVM và bấm vào liên kết "Hiển thị chủ đề" dưới tiêu đề phần "Chủ đề tại đống đổ nát". –

+7

'-XX: OnOutOfMemoryError =" kill -3% p "' - và bạn không cần phải phân tích cú pháp và chỉ định pid theo cách thủ công (https://forums.oracle.com/forums/thread.jspa?threadID=2374398&tstart= 60) – yetanothercoder

2

Có thể kích hoạt kết xuất chuỗi khi OnOutOfMemoryError được kích hoạt bằng cách sử dụng jstack. ví dụ: -

jstack -F pid > /var/tmp/<identifier>.dump 
0

Dựa trên câu trả lời được chấp nhận Tôi đã tạo lớp tiện ích. Cái này bạn có thể định nghĩa như là một Spring bean và tất cả các bạn đã được thiết lập với việc khai thác mở rộng.

import java.util.Iterator; 
import java.util.Map; 

import javax.annotation.PostConstruct; 

import org.apache.commons.lang3.exception.ExceptionUtils; 
import org.slf4j.Logger; 
import org.slf4j.LoggerFactory; 

public class UncaughtExceptionLogger { 

    private final static Logger logger = LoggerFactory.getLogger(UncaughtExceptionLogger.class); 

    @PostConstruct 
    private void init() { 
     Thread.setDefaultUncaughtExceptionHandler(new Thread.UncaughtExceptionHandler() { 
      public void uncaughtException(final Thread t, final Throwable e) { 
       String msg = ExceptionUtils.getRootCauseMessage(e); 
       logger.error(String.format("Uncaght exception handler captured expcetion '%s'", msg), e); 
       if (msg.contains("unable to create new native thread")) { 
        String dump = captureThreadDump(); 
        logger.error(String.format(
          "OutOfMemoryError has been captured for threads limit. Thread dump: \n %s", dump), e); 
       } 
       if (ExceptionUtils.getRootCause(e) instanceof OutOfMemoryError) { 
        String dump = captureThreadDump(); 
        logger.error(String.format("OutOfMemoryError has been captured. Thread dump: \n %s", dump), e); 
       } 
      } 
     }); 
    } 

    public static String captureThreadDump() { 
     /** 
     * http://stackoverflow.com/questions/2787976/how-to-generate-thread- 
     * dump-java-on-out-of-memory-error 
     * http://henryranch.net/software/capturing-a-thread-dump-in-java/ 
     */ 
     Map<Thread, StackTraceElement[]> allThreads = Thread.getAllStackTraces(); 
     Iterator<Thread> iterator = allThreads.keySet().iterator(); 
     StringBuffer stringBuffer = new StringBuffer(); 
     while (iterator.hasNext()) { 
      Thread key = (Thread) iterator.next(); 
      StackTraceElement[] trace = (StackTraceElement[]) allThreads.get(key); 
      stringBuffer.append(key + "\r\n"); 
      for (int i = 0; i < trace.length; i++) { 
       stringBuffer.append(" " + trace[i] + "\r\n"); 
      } 
      stringBuffer.append(""); 
     } 
     return stringBuffer.toString(); 
    } 
} 
Các vấn đề liên quan