2011-11-11 18 views
5

Tôi đã theo dõi ứng dụng java của mình bằng profiler để biết rò rỉ bộ nhớ. Và tôi đã nhận lớp mà dùng gần 80% bộ nhớ đó làLàm cách nào để tăng mức ưu tiên của FinalizerThread để thu thập các đối tượng trong GC

java.lang.ref.Finalizer 

Sau đó, tôi google nó cho lớp trên và tìm thấy bài viết tuyệt vời http://www.fasterj.com/articles/finalizer1.shtml

Bây giờ có thể bất kỳ một đề nghị tôi làm thế nào để tăng ưu tiên FinalizerThread để thu thập các đối tượng đó trong GC.

Một điều nữa tôi đang phải đối mặt với vấn đề này trên Linux với phiên bản kernel Linux 2.6.9-5.ELsmp (i386) Linux 2.6.18-194.17.4.el5 (i386) nhưng nó làm việc tốt (không có Lỗi OOM) trên Linux 2.6.18-128.el5PAE (i386).

Sự cố này có phải do hạt nhân Linux không? Có biến JVM nào để cải thiện ưu tiên của FinalizerThread không?

Thanx trước.

+1

Câu hỏi hay, tôi nghĩ bạn cần nói chung giảm thiểu việc sử dụng Finalizers. –

+0

Có lẽ ở chế độ PAE, bạn chỉ cần có nhiều bộ nhớ hơn (không phải PAE được giới hạn ở 4GB) - hãy kiểm tra 'free'. Tôi không nghĩ rằng phiên bản hạt nhân được chơi ở đây. –

+0

Cảm ơn Dan, Như Peter đã đề xuất bên dưới, tôi hiện đang kiểm tra với hệ thống tệp. – user1041580

Trả lời

2

Để trả lời câu hỏi theo nghĩa đen bạn có thể thực hiện việc này. Tuy nhiên như được nêu dưới đây, nó có thể là vô nghĩa, đặc biệt là các chủ đề đã có một ưu tiên cao.

for(Thread t: Thread.getAllStackTraces().keySet()) 
    if (t.getName().equals("Finalizer")) { 
     System.out.println(t); 
     t.setPriority(Thread.MAX_PRIORITY); 
     System.out.println(t); 
    } 

in

Thread[Finalizer,8,system] 
Thread[Finalizer,10,system] 

Trừ khi bạn đang sử dụng 100% của tất cả các lõi của bạn, hoặc gần với nó, ưu tiên không quan trọng vì ngay cả những ưu tiên thấp nhất sẽ nhận được càng nhiều CPU như nó muốn.

Lưu ý: Trên Linux, nó sẽ bỏ qua các ưu tiên đã nêu trừ khi bạn là người chủ.

Thay vào đó bạn nên giảm công việc mà trình hoàn thiện đang thực hiện. Lý tưởng nhất là nó không nên có bất cứ điều gì để làm. Một nguyên nhân của tải trọng cao trong finalizer là tạo ra các tài nguyên cần được đóng lại nhưng đang bị loại bỏ. Thay vào đó, bạn nên thử và xác định nguồn lực nào đang được hoàn thiện và đảm bảo rằng chúng không cần phải làm bất cứ điều gì khi finalize() được gọi, lý tưởng là không sử dụng phương pháp này ở tất cả.

Có thể các tài nguyên mất nhiều thời gian hơn để đóng phiên bản hạt nhân Linux cũ hơn. Tôi sẽ kiểm tra xem phần cứng có giống hệt như điều này có nghĩa là mất nhiều thời gian hơn để dọn sạch tài nguyên. (Nhưng sửa chữa thực sự là để đảm bảo nó không cần phải làm điều này)

+0

java có thể tạo sự khác biệt. Bởi vì đầu tiên hai Linux (nơi OOM phát sinh), đang sử dụng java bit 64 và một trong đó nó làm việc tốt, đang sử dụng 32 bit? – user1041580

+0

Phiên bản Java, cho dù bạn đang sử dụng 64 bit hay 32 bit, phần cứng nào bạn đang sử dụng CPU, bộ nhớ, đĩa, băng thông mạng, khối lượng công việc, ví dụ: là nó làm công việc khác nhau, làm thế nào bận rộn các nguồn lực được đóng cửa là ví dụ nếu họ kết nối với cơ sở dữ liệu hoặc dịch vụ, tất cả sẽ tạo sự khác biệt trong trường hợp này. Phiên bản hạt nhân có thể tạo sự khác biệt nhưng tôi sẽ kiểm tra danh sách đầu tiên trước tiên. –

+0

Nếu bạn có phiên bản Java cũ hơn, phiên bản 64 bit có thể sử dụng nhiều bộ nhớ hơn phiên bản 32 bit. Nếu bạn có phiên bản mới nhất, sự khác biệt sẽ nhỏ hơn nhiều (vì nó sử dụng '-XX: + UseCompressedOops') Sửa lỗi thực sự là sửa mã, chứ không phải là tinker với JVM. –

2

Chủ đề finaliser hiếm khi được thực hiện nhiều công việc. Các tài nguyên nên đã được phát hành. Đảm bảo mã của bạn đang xử lý tài nguyên theo cách tiêu chuẩn.

Java SE 7:

try (final Resource resource = acquire()) { 
    use(resource); 
} 

Pre-Java SE 7:

final Resource resource = acquire(); 
try { 
    use(resource); 
} finally { 
    resource.release(); 
} 
0

Như Tom Hawtin chỉ ra, bạn có thể có được giữ của FinalizerThread bằng cách tạo ra một phương pháp finalize() mà các cuộc gọi Thread.currentThread() và sau đó stashes nó trong một tĩnh. Bạn cũng có thể thay đổi mức độ ưu tiên của nó.

Nhưng có một cơ hội tốt là nó sẽ không thực hiện tốt. Có khả năng chỉ là một chuỗi finalizer. Và vấn đề là có khả năng là một trong hai rằng:

  • thread không thể theo kịp vì chỉ đơn giản là quá nhiều việc cần phải làm, hoặc
  • thread đang bị chặn bởi một cái gì đó bạn đang làm trong finalizer phương pháp.

(Và, tôi mong đợi thread finalizer để đã được đánh dấu là ưu tiên cao.)

Nhưng một trong hai cách, tôi nghĩ rằng một giải pháp tốt hơn là để thoát khỏi sự finalize() phương pháp. Tôi cá là họ đang làm điều gì đó không cần thiết ... hay tinh ranh. Đặc biệt, việc sử dụng finalizers để lấy lại tài nguyên từ các đối tượng bị loại bỏ là một cách thức kém để giải quyết vấn đề cụ thể đó. (Xem câu trả lời của Tom Hawtin.)

+0

Nhận lấy đối tượng chuỗi finaliser? Dễ dàng. Tạo một đối tượng với một finaliser đã lưu trữ 'Thread.currentThread()' trong một tĩnh. –

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