9

Một trong những rò rỉ bộ nhớ mà tôi đã phát hiện trong ứng dụng của chúng tôi là trường tĩnh riêng java.awt.Window.allWindows, theo dõi mọi Cửa sổ được khởi tạo. Chúng tôi có các hộp thoại được tạo ra, sử dụng, và sau đó bị lãng quên, và kỳ vọng là chúng sẽ biến mất và được thu gom rác. Trường riêng tư này giữ chúng trong phạm vi, vô thời hạn, cho đến khi phương thức dispose() được gọi trên chúng. Và theo định nghĩa, chúng tôi không thể làm điều đó khi họ đã đi ra khỏi phạm vi.Tại sao bạn phải vứt bỏ() một java.awt.Window không nằm trong phạm vi?

Tôi không hiểu tại sao điều này được thiết kế theo cách này. Có vẻ như trái ngược với tinh thần thu gom rác thải phải cho hệ thống biết rõ khi nào tôi làm xong với một đối tượng Window. Rõ ràng là tôi đã làm xong với nó, vì nó nằm ngoài phạm vi.

Tôi hiểu phương thức dispose() đang làm: loại bỏ các đối tượng ngang hàng hệ thống. Tôi hiểu rằng đây là bên ngoài của Java và bạn cần một số cách để làm điều đó và Swing đó không nên chỉ mất theo dõi của những đối tượng, nếu không nó sẽ có một rò rỉ bộ nhớ. Nhưng những gì được thực hiện bằng cách giữ một tham chiếu đến cửa sổ của tôi xung quanh mãi mãi, khi tôi sẽ không bao giờ sử dụng nó một lần nữa?

Ai đó có thể giải thích lý do tại sao điều này là cần thiết?

+0

Khi 'removeNotify' được gọi,' Window' sẽ bị xóa khỏi 'allWindows'. 'Window' chứa các tài nguyên gốc, và vì vậy nên được xử lý theo cùng một cách như thể nó là một kết nối cơ sở dữ liệu. –

+0

Tôi đã cảm thấy rằng khi các kết nối cơ sở dữ liệu của tôi đi ra khỏi phạm vi, chúng tự động đóng lại.Tôi có lẽ sai về điều đó. :) Ngày nay, tất cả những gì được quản lý cho tôi bởi một máy chủ ngoại trừ các chương trình ngắn. – skiphoppy

Trả lời

14

Tôi ghét phải nói điều đó, nhưng đó chỉ là cách GUI hoạt động.

Windows không bị chặn. Có nghĩa là khi bạn tạo một mã, mã của bạn tiếp tục thực thi.

Điều này có nghĩa là Cửa sổ của bạn có thể nằm ngoài phạm vi ngay sau khi tạo, trừ khi bạn lưu trữ một cách rõ ràng tham chiếu đến nó ở một nơi khác. Cửa sổ vẫn còn trên màn hình tại thời điểm này.

Điều này cũng có nghĩa là bạn cần một số cách khác để loại bỏ nó khi bạn hoàn thành nó. Nhập phương thức Window dispose(), có thể được gọi từ bên trong một trong những người nghe của Window.

+1

D'oh! Tôi hiểu rồi! Mọi người tạo cửa sổ mọi lúc mà họ không giữ tài liệu tham khảo, nhưng các cửa sổ vẫn hiển thị và đang chạy. Tôi chỉ không nghĩ về điều đó bởi vì trong tình huống này, chúng tôi ngay lập tức sử dụng cửa sổ sau đó làm cho nó vô hình, sau đó quên nó (đi ra khỏi phạm vi). Bây giờ tôi thấy lý do tại sao đây là mặc định cho các cửa sổ. Tôi biết có một trường hợp sử dụng hợp lý ở đâu đó. :) – skiphoppy

+0

Ồ, đúng, tôi nên chỉ ra rằng Cửa sổ vẫn còn trên màn hình khi biến của nó nằm ngoài phạm vi. Tôi sẽ chỉnh sửa câu trả lời đó trong câu trả lời của tôi trong trường hợp ai đó bỏ lỡ điều đó. – Powerlord

2

Điều này có thể giải thích nó: AWT Threading Issues

đơn giản, có rất nhiều xảy ra trong JVM hơn là chỉ những thành phần có thể nhìn thấy, với chủ đề nền và vân vân. Các luồng này và các tài nguyên khác được duy trì cho đến khi Cửa sổ cuối cùng trên JVM được xử lý, sau đó chúng được dọn dẹp và JVM sau đó có thể thoát sạch. Vì vậy, mỗi cửa sổ, khung và cửa sổ hộp thoại mà bạn sử dụng chủ yếu là giữ một khóa trên JVM để ngăn chặn nó thoát, và bạn phải tự quản lý điều này với các cuộc gọi đến dispose().

Tôi đồng ý rằng đó là một phần của một trình điều khiển. Tôi đã chạy afoul này một vài lần bản thân mình.

1

Trong Java khi bạn có mã gốc (đó là những gì bạn bè của các thành phần cửa sổ này), bạn cần giữ một tham chiếu để ngăn bộ thu gom rác cố gắng thu gom rác trong khi các con trỏ gốc vẫn còn xung quanh, mà sẽ gây ra tất cả các loại công cụ xấu (VM tai nạn, vv).

Xem, ví dụ: thảo luận here.

1

Phương thức dispose() hủy đối tượng được giữ bởi đối tượng WindowEvent. Nó không giết ứng dụng/p

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