2010-12-29 59 views
6

Trong một cuộc gọi phương thức, nếu tôi tạo một đối tượng trong suốt cuộc gọi đó. Khi nào thì các vật thể đó được thu gom rác?Vòng đời của các đối tượng Java cục bộ được tạo trong khi gọi phương thức

Chúng được đặt trên đống và sau đó rác được thu thập cùng với các đối tượng khác trên heap. Hoặc là chúng thu thập rác trước đó bởi vì chúng không cần thiết. Việc thực hiện phương thức đó đã hoàn thành.

Trả lời

6

Đối tượng được tạo trong phạm vi phương pháp đủ điều kiện để thu thập rác khi phương thức được đóng - trừ khi tham chiếu đó được trả lại dưới dạng giá trị trả về. Trong trường hợp đó, người gọi có thể hoặc không thể treo vào tham chiếu đó và ngăn chặn nó được gc'd.

Vì bộ thu gom rác chạy trên chỉ riêng của nó theo đèn riêng, bạn không nhất thiết phải biết khi nào một đối tượng được làm sạch hoặc có vật thể được phân bổ ở nơi khác đủ điều kiện không.

+0

@duffymo: Điều này có phụ thuộc vào việc tham chiếu của đối tượng mới được tạo có tồn tại sau khi trả về hàm không? một đối tượng được lưu trữ trong một bộ sưu tập nằm trong phạm vi của người gọi. – Cratylus

+0

@user - Trong trường hợp đó phạm vi của đối tượng đã thay đổi và có thể không bị ảnh hưởng bởi GC. – Jeremy

+0

"Đối tượng được tạo trong phạm vi phương thức ..." với tôi có nghĩa là đối tượng không được người dùng chuyển vào. Bạn đang đúng về một điều: nếu đối tượng được tạo ra trong phạm vi được truyền lại dưới dạng giá trị trả lại, thì người gọi có thể giữ tham chiếu và ngăn không cho nó bị gc'd. Tôi sẽ sửa đổi câu trả lời của tôi. – duffymo

3

Đây không phải là dễ dàng như vậy - vào cuối mỗi đối tượng được tạo ra trong một số phương pháp.

Máy ảo/trình biên dịch cần thực hiện phân tích đường dẫn thoát để phát hiện xem có tham chiếu của đối tượng này theo cách nào đó có thể thoát hay không - hãy tưởng tượng gọi newObject.toString(). Bạn và tôi biết (hy vọng) rằng điều này sẽ không gây hại và đối tượng vẫn không được tham chiếu, vì nó sẽ không liên kết chính nó với một biến toàn cầu. Nhưng máy ảo thì không.

Trong khi một VM hiện đại sẽ thực hiện phân tích và xử lý các đối tượng sống ngắn thực sự đặc biệt trong thu gom rác, từ quan điểm "cấp cao", chúng chỉ là các đối tượng. Mọi thứ khác là tối ưu hóa mức độ tinh vi thấp.

Và dù sao, như duffymo nói - khi chính xác đối tượng này được giải thoát thì không chắc chắn.

1

Thực tế là việc thực hiện phương pháp đã kết thúc và hiện tại đối tượng nằm ngoài phạm vi không liên quan.
Thu thập rác là một hoạt động tiềm ẩn của hệ thống thời gian chạy chạy trong một luồng riêng biệt song song với mã của bạn, thực hiện một thuật toán thu gom rác cụ thể.
Chuỗi bộ sưu tập rác chạy vào thời điểm không thể đoán trước - nhưng rất thường xuyên, mỗi giây hoặc hơn theo tài liệu java và khi bộ nhớ gần hết, đánh giá đối tượng nào đủ điều kiện để thu gom rác tức là không có tham chiếu đến chúng từ gốc con trỏ ví dụ biến tĩnh.
Vì vậy, mọi đối tượng có thể truy cập bằng con trỏ gốc đều được đánh dấu và sau đó đệ quy các đối tượng được tham chiếu bởi các đối tượng này, v.v.
Điều này có nghĩa là quét toàn bộ không gian quy trình. Sau khi thực hiện, tất cả các đối tượng không "đánh dấu" từ lần quét trước đó sẽ đi vào danh sách miễn phí (là GC'd).
Đây là một hoạt động nặng như bạn có thể thấy.

Việc thực hiện phương thức đó đã hoàn tất .

Vì vậy, thực tế là bạn nằm ngoài phạm vi của phương pháp bạn gọi vì nó đã hoàn thành, không liên quan. Nó không có nghĩa là thời gian chạy biết tại thời điểm đó đối tượng được thực hiện (vì GC được chạy song song).
Nó không giống như trong C++ mà vào cuối phương thức mà người lập trình sẽ gọi là xóa trên đối tượng vì nó không cần thiết. Không "xóa" được tự động gọi vào cuối phương thức trong Java.
Chủ đề GC cuối cùng sẽ nhận ra rằng không có thêm tham chiếu đến đối tượng được phân bổ trên heap theo phương thức và CG nó.
Bạn có thể gọi GC bất cứ lúc nào nếu bạn muốn bằng cách:

System.gc(); 

Nhưng GC sẽ chạy sớm hay muộn anyway.
Một điều cần lưu ý là miễn là có một tham chiếu đến một phương pháp bởi một con trỏ gốc nó không thể là của GC. Vì vậy, nếu trong phương pháp của bạn, bạn tạo thông qua new một đối tượng trên heap và bạn lưu trữ tham chiếu trong vùng chứa tĩnh hoặc trả lại cho người gọi, đối tượng sẽ sống ngoài phương thức.

+0

Bộ sưu tập rác đã được cải thiện rất nhiều kể từ ngày Smalltalk. Không có VM cấp thương mại nào như thế này nữa. Rất nhiều infos có thể là google về các thuật toán thực tế. – mtraut

+0

System.gc() ít nhiều là một gợi ý cho VM rằng bây giờ bạn nên kích hoạt một gc. Bạn không thể tin rằng điều này được thừa nhận VÀ (ngay cả khi VM đồng ý) bạn có thể tin rằng sau khi gc() rác được thu thập. Điều này luôn luôn không đồng bộ. – mtraut

+0

@mtraut: Tôi cũng đang hướng tới điều này.Nhưng javadocs dường như nói khác: 'Khi điều khiển trả về từ lời gọi phương thức (System.gc), Máy ảo Java đã thực hiện một nỗ lực tốt nhất để lấy lại không gian từ tất cả các đối tượng bị loại bỏ ' – Cratylus

2

Object Life Cycle

Một chương trình java tạo ra nhiều đối tượng từ các lớp khác nhau. Đối tượng trong Java, tương tác bằng cách gửi tin nhắn cho nhau. Sau khi chúng được thực hiện xong, các đối tượng này sau đó được thu gom rác. Sau quá trình thu gom rác, Hệ điều hành xác nhận lại các tài nguyên được cấp phát cho các đối tượng này sẽ được các đối tượng mới sử dụng thêm.

Dưới đây là các giai đoạn mà một đối tượng Java đi qua khỏi vòng đời của nó:

1. Lớp Đang tải

Trước khi tạo đối tượng từ một lớp học, lớp nên được nạp vào bộ nhớ từ đĩa. Trình nạp lớp java nạp tệp lớp vào bộ nhớ.

Khi lớp học được tải?

  • khi lần đầu tiên đối tượng được tạo.

  • bất kỳ trường hoặc phương pháp tĩnh nào được truy cập lần đầu tiên.

initializers tĩnh

Java sẽ tìm kiếm bất kỳ initializers tĩnh và khởi tạo các lĩnh vực tĩnh mà là một phần của lớp và không nằm trong một trường hợp cụ thể của lớp (đối tượng).

3. tạo Object

Object là một thể hiện của lớp. Nó được tạo trong các tình huống dưới đây:

Tuyên bố: khi bạn khai báo đối tượng, ví dụ: ClassA objA; Giải thích: khi mới được sử dụng để phân bổ đối tượng mới trong bộ nhớ heap, ví dụ: ClassA mới(); Khởi tạo: đối tượng mới được xây dựng, ví dụ: ClassA(); 4. Việc sử dụng đối tượng

ở giai đoạn này, chương trình có thể sử dụng đối tượng bằng cách truy cập các trường hoặc phương thức gọi.

5. Cleanup

Đây là giai đoạn cuối cùng của đối tượng Java, nơi họ được tái chế và bộ nhớ được tuyên bố chủ quyền hệ điều hành.

điều gì sẽ xảy ra khi hủy?

Đối tượng được xóa khỏi bộ nhớ. Java giảm các tham chiếu nội bộ của nó vào đối tượng này. Bộ sưu tập rác (GC), chạy mà giải phóng các đối tượng không cần thiết nữa, tức là không có tham chiếu đến đối tượng này. Hoàn thành: GC cung cấp cho các đối tượng cơ hội cuối cùng để dọn sạch mọi tài nguyên khác bằng cách gọi phương thức finalize() của nó.

khi điều đó xảy ra?

khi đối tượng nằm ngoài phạm vi. tức là {… objA…}, đây} trở thành phạm vi. tại thời điểm này, Java chạy kiểm tra thời gian cho các tài liệu tham khảo và cho phép GC tái chế đối tượng này. khi số tham chiếu đến đối tượng này trong bộ nhớ thời gian chạy java trở thành số không (0). khi đối tượng được đặt rõ ràng thành rỗng nghĩa là objA = null ;, GC được gọi là phương thức final2() được gọi là .

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