2013-03-10 40 views
17

Tôi đang đọc về bộ sưu tập Rác và tôi nhận được kết quả tìm kiếm khó hiểu khi tôi tìm kiếm các bộ sưu tập rác theo chuỗi ký tự.Thu gom rác của các chuỗi ký tự

tôi cần làm rõ về điểm sau đây:

  1. Nếu một chuỗi được định nghĩa là đen tại thời gian biên dịch [ví dụ: String str = "java"] sau đó nó sẽ được thu gom rác?

  2. Nếu sử dụng phương pháp tập luyện [ví dụ: String str = new String("java").intern()] thì nó có bị thu gom rác không? Đồng thời, nó sẽ được xử lý khác với Chuỗi ký tự ở điểm 1.

  3. Một số địa điểm được đề cập rằng các chữ cái sẽ chỉ được thu gom rác khi lớp String sẽ được tải xuống? Điều đó có hợp lý không vì tôi không nghĩ rằng lớp học String sẽ bị xóa.

+2

1 - http://stackoverflow.com/questions/2202162/garbage-collection-and-strings; 2 - http://stackoverflow.com/questions/6470651/creating-a-memory-leak-with-java; 3 - String a = new String ("asd") -> "a" tham chiếu sẽ được thu thập rác, nhưng chỉ là một tham chiếu đến "asd" và "asd" sẽ ở đó mãi mãi. – user1050755

+0

Nếu bạn tìm kiếm nhiều hơn, bạn sẽ tìm thấy các địa điểm đề cập đến các chuỗi ký tự được tạo bằng cách sử dụng thực tập có thể được thu thập rác khi chúng sử dụng tham chiếu yếu nhưng tôi không thể xác nhận nó và đó là lý do tại sao tôi đã đăng như có rất nhiều phản ứng hỗn hợp. – Lokesh

Trả lời

18

Nếu chuỗi được định nghĩa là chữ theo thời gian biên dịch [ví dụ: String str = "java";] thì nó sẽ được thu gom rác?

Có thể là không. Các đối tượng mã sẽ chứa một hoặc nhiều tham chiếu đến các đối tượng String đại diện cho các chữ. Vì vậy, miễn là các đối tượng mã có thể truy cập được, các đối tượng String sẽ đến.

Có thể các đối tượng mã không thể truy cập được, nhưng chỉ khi chúng được nạp động ... và trình nạp lớp của chúng bị hủy.

Nếu tôi sử dụng phương pháp tập luyện [e.g: String str = new String("java").intern()] sau đó nó sẽ được thu gom rác?

Đối tượng được trả về bằng lệnh intern sẽ là cùng một đối tượng đại diện cho số "java" chuỗi. (Các "java" đen là thực tập nội trú vào thời điểm lớp tải. Khi bạn sau đó thực tập sinh mới được xây dựng String đối tượng trong đoạn mã của bạn, nó sẽ tra cứu và trả lại trước thực tập nội trú "java" chuỗi.)

Tuy nhiên, thực tập nội trú chuỗi mà không phải là giống hệt với chuỗi literals có thể là rác được thu thập khi chúng trở nên không thể truy cập được. Không gian PermGen rác được thu thập trên tất cả các JVM HotSpot gần đây. (Trước Java 8 ... mà giọt PermGen hoàn toàn.)

Ngoài ra nó sẽ được đối xử khác với chuỗi chữ tại điểm 1.

Không ... vì nó là cùng một đối tượng như chuỗi chữ.

Và thực sự, một khi bạn hiểu những gì đang diễn ra, rõ ràng là các chuỗi ký tự không được xử lý đặc biệt. Nó chỉ là một ứng dụng của quy tắc "khả năng tiếp cận" ...

Một số nơi được đề cập rằng các bản sao sẽ chỉ được thu gom rác khi lớp học String sẽ được tải xuống? Nó có ý nghĩa bởi vì tôi không nghĩ rằng lớp học String sẽ không bao giờ được dỡ xuống.

Bạn nói đúng. Nó không có ý nghĩa. Các nguồn nói rằng không chính xác. (Sẽ hữu ích nếu bạn đăng URL để chúng tôi có thể đọc những gì họ đang nói cho chính mình ...)

+1

Đối với # 1, Khi bạn nói các đối tượng mã có chứa các tham chiếu đến các chuỗi ký tự String, bạn đang đề cập đến điều gì? – Mercenary

+4

Một nơi nào đó trong các đối tượng mã (bytecode hoặc được biên dịch gốc) sẽ có hướng dẫn cần tìm nạp tham chiếu đến đối tượng String tương ứng với chữ. Hoặc tham chiếu được nhúng trong chính mã hoặc nó được lưu trữ trong một khung riêng tư được liên kết với mã. Dù bằng cách nào, tham chiếu là "có thể truy cập" miễn là mã * có thể * được thực thi. –

+0

Cảm ơn. Và, là một phần của chuỗi thực tập trong vùng phương pháp trong JVM? – Mercenary

9

Trong trường hợp bình thường, chuỗi và lớp chuỗi được phân bổ vào thế hệ vĩnh viễn của JVM ("PermGen") và thường sẽ không bao giờ được thu thập. Các chuỗi được tập trung (ví dụ: mystring.intern()) được lưu trữ trong một nhóm bộ nhớ thuộc lớp String trong permgen, và nó đã từng là trường hợp quá tải có thể gây ra rò rỉ không gian. không có tài liệu tham khảo khác tồn tại. Rõ ràng điều này không còn đúng, ít nhất là JDK 1.6 (xem, ví dụ: here).

Để biết thêm thông tin về permgen, this là tổng quan về chủ đề. (Lưu ý: liên kết đó đến blog được liên kết với sản phẩm. Tôi không có bất kỳ liên kết nào với blog, công ty hoặc sản phẩm nhưng mục nhập blog hữu ích và không liên quan nhiều đến sản phẩm.)

+2

Điều này không đúng. Không gian PermGen >> là << rác được thu thập. –

+0

Bạn là đúng tất nhiên. Ý định của tôi là chỉ để nói rằng dữ liệu được phân bổ vào permgen sẽ không nhận được GC'ed trong những hoàn cảnh bình thường, nhưng tôi bị đánh giá sai. Hơi rephrased. – jacobm

+0

Trên thực tế, đào sâu hơn, tôi phát hiện ra rằng nó không còn đúng sự thật rằng chuỗi interned không nhận được rác thu thập được. (Điều này không phải vì không gian permgen, đó là do việc thực hiện 'String # intern'.) Thay đổi câu trả lời của tôi để phản ánh điều đó. – jacobm

0
  1. Chuỗi chữ sẽ vẫn còn trong bộ nhớ miễn là chương trình có trong bộ nhớ.
  2. str sẽ được thu thập rác, nhưng theo nghĩa đen được tạo ra từ sẽ không.
  3. Điều đó có ý nghĩa hoàn hảo, vì lớp chuỗi được tải xuống khi chương trình được tải xuống.
+0

Bạn có thể cho tôi ví dụ về Chuỗi có thể được tải không? Như tôi tin rằng String literals phải được sử dụng trong các lớp java cũng như và String literals là hằng số, việc dỡ hàng có thể cần phải nạp CLassLoader theo kiến ​​thức của tôi. Bạn có đồng ý không? – Lokesh

+0

Một chuỗi chữ không thể, theo hiểu biết của tôi được dỡ bỏ theo chương trình. Họ sẽ được dỡ bỏ, hoặc bị phá hủy, khi chương trình chấm dứt. – fredrik

+1

@fredrik - chúng cũng có thể là rác được thu thập nếu một lớp đã được tải động được tải xuống. Và điều đó có thể xảy ra trong khi JVM đang chạy bình thường. –

-3

intern() phương pháp kiểm tra tính khả dụng của đối tượng trong nhóm Chuỗi. Nếu đối tượng/chữ có sẵn thì tham chiếu của nó sẽ được trả lại. Nếu chữ không có trong hồ bơi thì đối tượng được nạp trong vùng perm (String pool) và sau đó tham chiếu đến nó sẽ được trả về. Chúng ta phải sử dụng phương pháp intern() một cách thận trọng.

+0

Chữ thường nằm trong hồ bơi, theo định nghĩa. – EJP