2010-11-18 37 views
14

Điều này phần lớn là do tò mò.Sử dụng tốt phương thức finalize()

Tôi đã lang thang nếu có ai gặp phải bất kỳ cách sử dụng nào tốt cho Object.finalize() ngoại trừ các mục đích gỡ lỗi/ghi nhật ký/lược tả?

Nếu bạn chưa gặp phải bất kỳ điều gì bạn sẽ nói, việc sử dụng tốt sẽ là gì?

+2

Bạn có thể sử dụng nó làm điểm dừng cửa hoặc neo thuyền :-) –

+0

: Bạn có nghĩa là nó đủ nặng hoặc không nổi? – Simeon

Trả lời

7

Nếu đối tượng Java của bạn sử dụng JNI để hướng dẫn mã nguồn gốc cấp phát bộ nhớ riêng, bạn cần sử dụng hoàn thiện để đảm bảo nó được giải phóng.

+0

Có ai đó không đồng ý với điều này không? – bmargulies

+1

Tại sao bạn không thể xử lý bộ nhớ riêng như tất cả các tài nguyên khác (mở tệp, kết nối DB) và yêu cầu đóng cửa rõ ràng? Đối tượng Java của bạn chỉ có thể có một 'dispose()' hoặc 'close()' để làm sạch. – sleske

+1

Những thứ thường có finalizers. 'close()' cho phép bạn lấy các tài nguyên được giải phóng sớm hơn, nhưng JVM vẫn sử dụng trình hoàn thiện để đảm bảo rằng chúng được giải phóng cuối cùng. – bmargulies

2

Tôi sử dụng nó để ghi dữ liệu trở lại cơ sở dữ liệu khi sử dụng tham chiếu mềm để lưu vào bộ nhớ cache đối tượng được cơ sở dữ liệu lưu trữ.

+4

Bạn nên để một số thư viện xử lý những điều này. – aioobe

+4

Vâng. Tôi biết ... – aioobe

+1

: D khiến tôi cười ... – Simeon

3
  1. đóng các kết nối bên ngoài (db, ổ cắm, v.v ...)
  2. đóng các tệp đang mở. thậm chí có thể cố gắng viết một số thông tin bổ sung.
  3. ghi nhật ký
  4. nếu lớp này chạy các quy trình bên ngoài chỉ tồn tại khi đối tượng tồn tại, bạn có thể thử tiêu diệt chúng tại đây.

Nhưng nó chỉ là một dự phòng được sử dụng là cơ chế "bình thường" không hoạt động. Cơ chế bình thường nên được bắt đầu một cách rõ ràng.

+0

Thực sự quan trọng chỉ sử dụng để bảo vệ chống lại mã lỗi. Hệ điều hành giới hạn số lượng tệp mở cho mỗi quá trình, bạn có thể chạy hết các tệp xử lý lâu trước khi finalize() được gọi. – josefx

+2

Đóng các tệp đang mở để hoàn tất? Kể từ khi hoàn thành có thể không bao giờ được gọi là trong suốt cuộc đời ứng dụng bạn có chắc đây là một ý tưởng tốt? Tôi sẽ nói rằng bạn cần phải đóng các tập tin mở trong một khối cuối cùng (hoặc một cái gì đó mà bạn chắc chắn được thực hiện). – Simeon

+0

@Simeon Tôi nghĩ rằng AlexR có nghĩa là đây là những nhược điểm (như anh ta nói trong câu trả lời của mình) trong trường hợp vì lý do nào đó các tập tin không bị đóng khi chúng được cho là không phải. mọi lúc. – blwy10

2

Tài nguyên phát hành phải được phát hành theo cách thủ công trong các trường hợp bình thường, nhưng không được giải phóng vì một số lý do. Có lẽ với viết một cảnh báo cho nhật ký.

+0

Ooh, ghi vào nhật ký là một ý tưởng hay.Sau đó, bạn không chỉ có được điều phát hành nhưng bạn nhận được một số cảnh báo về vấn đề này. Tôi không bao giờ nghĩ về điều đó. Tôi có một lớp tôi nên thực hiện thay đổi đó để ... – Jay

-1

Tôi thấy một cách sử dụng tốt để hoàn thiện(): giải phóng tài nguyên có sẵn với số lượng lớn và không độc quyền.

Ví dụ: theo mặc định, có 1024 tệp xử lý có sẵn cho quy trình Linux và khoảng 10000 cho Windows. Điều này là khá nhiều, vì vậy đối với hầu hết các ứng dụng nếu bạn mở một tập tin, bạn không cần phải gọi .đóng() (và sử dụng thử xấu xí ... cuối cùng là khối), và bạn sẽ OK - cuối cùng() sẽ miễn phí nó cho bạn một thời gian sau đó. Tuy nhiên đối với một số đoạn mã (như các ứng dụng máy chủ chuyên sâu), việc giải phóng tài nguyên với .close() là phải, nếu không cuối cùng() có thể được gọi là quá muộn cho bạn và bạn có thể hết các tập tin. Kỹ thuật tương tự được sử dụng bởi Swing - tài nguyên hệ điều hành để hiển thị cửa sổ và bản vẽ không được phát hành bởi bất kỳ phương thức .close() nào, nhưng chỉ bằng cách hoàn thành(), vì vậy bạn không phải lo lắng về tất cả. các phương thức close() hoặc .dispose() như trong SWT chẳng hạn.

Tuy nhiên, khi có số lượng tài nguyên rất hạn chế hoặc bạn phải 'khóa' tài nguyên để sử dụng tài nguyên, hãy nhớ 'mở khóa' tài nguyên đó. Ví dụ: nếu bạn tạo khóa tệp trên tệp, hãy nhớ cũng xóa khóa này, nếu không sẽ không ai đọc được hoặc ghi tệp này và điều này có thể dẫn đến deadlocks - sau đó bạn không thể dựa vào finalize() để xóa khóa này cho bạn - bạn phải làm điều đó theo cách thủ công ở đúng nơi.

+1

-1: đó là chiều cao của sự thô lỗ đối với một ứng dụng dựa vào finalizer để đóng một tập tin xử lý, khi nó rất dễ dàng để gọi 'close()'. –

+1

gọi .close() không phải là dễ dàng chút nào: việc xử lý gần đúng 100% đòi hỏi hai lần thử ... mệnh đề (một lần thử ... cuối cùng là để ngậm(), và lệnh close() phải được kèm theo thử ... bắt, mà sau đó sẽ đăng nhập lỗi để ngăn chặn mất trường hợp ngoại lệ ban đầu), càng có nhiều tệp bạn đang làm việc, tình hình tồi tệ hơn, ví dụ làm việc với hai tệp cùng lúc yêu cầu 4 lần thử ... bắt khối - những gì một mess bây giờ so sánh điều này với sự dễ dàng làm việc với các tập tin trong ngôn ngữ kịch bản, như Perl ví dụ - bạn không phải gọi gần() trong tất cả các nơi! – iirekm

5

muộn để bên đây nhưng nghĩ rằng tôi vẫn sẽ kêu vang trong:

Một trong những ứng dụng tốt nhất mà tôi đã tìm thấy cho finalizers là để gọi các phương thức chấm dứt rõ ràng mà, cho những gì bao giờ lý trí, không được gọi. Khi điều này xảy ra, chúng tôi cũng đăng nhập vấn đề vì nó là một BUG!

Bởi vì:

  • Không có gì bảo đảm rằng finalizers sẽ được thực hiện kịp thời (hoặc kỹ thuật nào cả), mỗi đặc tả ngôn ngữ
  • Thực hiện phần lớn là phụ thuộc vào việc thực hiện JVM
  • Thực hiện có thể đôi khi bị trì hoãn nếu GC có mức ưu tiên luồng thấp hơn

Điều này chỉ để lại một số tác vụ mà chúng có thể giải quyết mà không gặp nhiều rủi ro.

+0

Rất hữu ích, cảm ơn :) – Simeon

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