2015-12-03 11 views
12

Tôi có một số quy trình Java và tôi đang cố quản lý các vùng đống được tạo khi xảy ra lỗi OOM. Khi tôi nói quản lý tôi muốn nóiJava Hết bộ nhớ tên tệp kết xuất đống tự động

  • tên đống đổ cách khác nhau, dựa trên quá trình có nguồn gốc
  • xóa cũ đống bãi để bảo tồn không gian đĩa

khi đổ đống trên oom với

-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/tmp 

JVM tạo tệp có tên sau java_pidXXXX.hprof trong thư mục được chỉ định/tmp (trong đó XXXX là PID của quy trình). Có cách nào để chỉ định một định dạng khác mà PID và DATE được sử dụng để tạo tên tệp không? Sau khi googling trong một giờ, tôi đã thử myPrefix_ $, {pid}, 'date' .. v.v. Hai điều duy nhất rằng công việc là

  1. không chỉ định tên tập tin và bạn sẽ có được java_pidXXXX.hprof
  2. chỉ định một tên tập tin tĩnh ví dụ \ tmp \ OOM.hprof.

nếu thư mục \ tmp không tồn tại, thư mục đó không được tạo, cũng không tạo vùng chứa.

Một ý kiến ​​cho rằng có thể sử dụng là thêm một lệnh về lỗi oom

-XX:OnOutOfMemoryError="doSomething.sh %p" 

nhưng tôi đã cố gắng để tránh nó như tôi cần phải triển khai "doSomething.sh"

+1

Tại sao bạn cần ngày trong tên? Nếu bạn muốn xóa các tập tin cũ hơn, bạn có thể làm điều đó bằng cách sửa đổi thời gian của các tập tin, bạn không cần ngày trong tên. – RealSkeptic

Trả lời

4

-XX:HeapDumpPath trên dòng lệnh không giúp bạn linh hoạt hơn những gì bạn đã khám phá. Tức là, bạn có thể:

  • Đặt tên thư mục, sau đó tên mặc định java_pidXXX.hprof sẽ được tạo trong thư mục đó.
  • Đặt tên tệp và tệp đó sẽ được sử dụng.

Mã có liên quan trong nguồn HotSpot là heapDumper.cpp. Đọc nó, nó không tìm kiếm bất kỳ "chuỗi ma thuật" bên trong đường dẫn nhất định:

  • Nó kiểm tra xem đường dẫn đã cho có phải là một thư mục hay không. Nếu vậy, hãy sử dụng nó làm tiền tố, thêm dấu tách tệp và sử dụng tên tệp mặc định được tạo từ các phần cứng được mã hóa bằng định dạng chuỗi không nằm trong tầm kiểm soát của bạn.
  • Nếu nó không phải là một thư mục, nó chỉ sử dụng nó như nó được.
  • Nếu nó không phải là bãi chứa đầu tiên trong cuộc đời của JVM này, nó cũng nối thêm một số thứ tự.

Vậy đó. Không phân tích đường dẫn nào ngoài việc xác định xem đó có phải là thư mục hay không.

Tính linh hoạt duy nhất bạn có thể thêm vào đó là sử dụng khả năng của trình bao khi bạn xây dựng tên trên dòng lệnh. Đó là lý do tại sao bạn có thể thấy một số ví dụ trên web sử dụng một cái gì đó như name_`date`.ext - điều này được xử lý bởi vỏ, thay thế `date` với ngày hiện tại sau khi. Tức là, tên tệp sẽ luôn có ngày/giờ khi trình bao xử lý lệnh và khởi động JVM - không phải ngày/giờ khi kết xuất được tạo. Nếu đó là đủ tốt cho bạn - bạn có thể sử dụng nó. Lưu ý rằng ngày nay nó được coi là chấp nhận được hơn để sử dụng cú pháp name_$(date).ext.

Nếu bạn chỉ cần ngày để có thể xóa tệp cũ thì bạn có thể xóa chúng dựa trên thời gian sửa đổi cuối cùng của tệp (tiện ích Unix/Linux find có thể giúp bạn với điều đó). Không cần phải có ngày trong tên.

Số $(date) (hoặc `date`) lừa không giúp bạn với PID. Vỏ cũng có thể thay thế PID hiện tại nếu bạn sử dụng $$ - nhưng đó là PID của vỏ xử lý dòng lệnh, không phải chính quá trình JVM. Tuy nhiên, nếu bạn khởi động ứng dụng JAVA của mình bằng cách sử dụng lệnh shell exec, nó sẽ nhận được ID quá trình giống như trình bao khởi tạo từ đó, vì vậy bạn có thể sử dụng $$ để xây dựng tên tệp của mình. Hãy nhớ rằng mặc dù không có gì sau khi exec sẽ được thực hiện từ kịch bản của bạn.

Vì vậy, bạn có thể thử thay đổi động tên tệp mà @apangin đề xuất trong câu trả lời của mình. Lưu ý, mặc dù, nó có thể sẽ là một chút khó khăn để xác định thời gian của bản thân bãi chứa, vì bạn sẽ muốn có tên tập tin được thiết lập trước khi OOM thực sự xảy ra.

6

HeapDumpPath là một tùy chọn VM có thể quản lý. Điều này có nghĩa là bạn có thể đặt nó thành bất kỳ thứ gì bạn muốn trong thời gian chạy bằng JMX.

String pid = ManagementFactory.getRuntimeMXBean().getName(); 
    pid = pid.substring(0, pid.indexOf('@')); 
    String date = new SimpleDateFormat("yyyyMMddHHmmss").format(new Date()); 
    String fileName = "/tmp/heap_" + pid + "_" + date + ".dump"; 

    HotSpotDiagnosticMXBean bean = ManagementFactory.newPlatformMXBeanProxy(
      ManagementFactory.getPlatformMBeanServer(), 
      "com.sun.management:type=HotSpotDiagnostic", 
      HotSpotDiagnosticMXBean.class); 
    bean.setVMOption("HeapDumpOnOutOfMemoryError", "true"); 
    bean.setVMOption("HeapDumpPath", fileName); 
Các vấn đề liên quan