2013-04-11 31 views
10

Ứng dụng tôi đang làm việc trên bất ngờ bị rơi vớiDebugging "Quá nhiều tập tin mở" vấn đề

java.io.IOException: ... Too many open files 

Như tôi hiểu vấn đề nó có nghĩa là tập tin được mở nhưng không đóng cửa.

Stacktrace tất nhiên xảy ra sau khi thực tế và chỉ có thể giúp hiểu trước khi xảy ra lỗi sự kiện.

Điều gì sẽ là cách thông minh để tìm kiếm cơ sở mã của bạn để tìm sự cố này dường như chỉ xảy ra khi ứng dụng chịu tải ứng suất cao.

+0

Bạn có đa luồng xử lý tệp hay tất cả được thực hiện trên cùng một chuỗi? Và bạn đã xem xét * Điều chỉnh đồng thời * để quản lý khối lượng công việc? – christopher

Trả lời

9

Tôi nghĩ rằng cách tốt nhất để sử dụng một công cụ thiết kế đặc biệt cho mục đích này, chẳng hạn như this one:

ít đại lý Java Đây là một công cụ theo dõi về nơi/khi/người mở tập tin trong JVM của bạn . Bạn có thể yêu cầu tác nhân theo dõi các hoạt động này để tìm hiểu về mẫu truy cập hoặc xử lý các rò rỉ và đổ danh sách các tệp đang mở và vị trí/khi/người đã mở chúng.

Ngoài ra, khi ngoại lệ "quá nhiều tệp đang mở", tác nhân này sẽ đổ danh sách, cho phép bạn tìm ra nơi một số lượng lớn mô tả tệp đang được sử dụng.

Tôi dường như nhớ YourKit cũng có một số cơ sở xung quanh điều này, nhưng không thể tìm thấy bất kỳ thông tin cụ thể nào vào lúc này.

3

Hệ điều hành nào? Nếu đó là linux/mac, có information under /proc sẽ hữu ích. Trên Windows, hãy sử dụng Process Explorer.

Theo như tìm kiếm cơ sở mã, có lẽ hãy tìm mã bắt hoặc tăng IOException - Tôi nghĩ rằng các phương thức I/O đã nắm bắt/nâng cao điều này có khả năng cao cần một cuộc gọi close().

9
  1. sử dụng lsof -p pid để kiểm tra xem nguyên nhân gây rò rỉ tham chiếu tệp;

  2. sử dụng ulimit -n để xem giới hạn tệp tham chiếu đã mở của một quy trình;

  3. kiểm tra mọi tài nguyên IO trong dự án của bạn, chúng có được phát hành đúng lúc không? Lưu ý rằng, File, Process, Socket (và kết nối Http) là tất cả tài nguyên IO.

  4. đôi khi, quá nhiều luồng cũng sẽ gây ra sự cố này.

+0

Điểm tuyệt vời về 'lsof' – JAM

+0

theo' lsof -p pid' Tôi có 3000 tệp được mở tại thời điểm này trong khi 'ulimit -n' là 2560. Có lẽ lệnh đầu tiên đếm một số thứ khác với tham chiếu tệp – cahen

+0

+1 điều này đã giúp tôi để gỡ lỗi một ứng dụng Android với việc sử dụng không đúng quy trình. Runtime.exec() với ping của hệ thống. Tôi đã phải gọi process.destroy() sau waitFor() để sửa chữa nó. – Rombus

3

Bạn đã thử gắn vào quy trình đang chạy bằng jvisualvm (Java 5.0 trở lên trong thư mục bin JDK). Bạn có thể mở tiến trình đang chạy và thực hiện một bãi chứa đống (nếu bạn có một JDK cũ hơn, bạn sẽ cần phải phân tích bằng cách sử dụng nhật thực hoặc intellij hoặc netbeans và cộng sự).

Trong JDK 7 nút kết xuất đống nằm trong tab "Màn hình". Nó sẽ tạo một tab kết xuất đống, tab phụ "Lớp học" mà bạn có thể kiểm tra và xem có bất kỳ lớp nào mở tệp tồn tại với số lượng cao hay không. Một tính năng hữu ích khác là so sánh đống đống, vì vậy bạn có thể lấy một đống tham chiếu, cho phép ứng dụng của bạn chạy một chút và sau đó lấy một đống kết xuất khác và so sánh hai (liên kết để so sánh là trên tab [heapdump] khi bạn lấy một cái.Ngoài ra còn có một lá cờ trong java cho một heapdump về tai nạn hoặc OOM ngoại lệ, bạn có thể đi xuống con đường đó nếu so sánh đống bãi không cung cấp cho bạn một lớp rõ ràng đang gây ra vấn đề. Ngoài ra, tab phụ "Instances" trong vùng heap dump sẽ hiển thị cho bạn những gì đã được phân bổ trong khoảng thời gian giữa hai vùng đống mà cũng có thể hữu ích.

jvisualvm là một công cụ tuyệt vời không nhận được đủ đề cập.

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