2013-07-15 10 views
8

Chạy một mã rất đơn giản để thử xem cách trình thu gom rác hoạt động như thế nào.Hành vi GC không mong đợi: một số dữ liệu luôn đi vào thế hệ nhiệm vụ

String a = null; 
while (true) { 
    a = new String(" no... "); 
} 

Tôi đang sử dụng ParallelGC. Tôi đã in kết quả GC và đây là GC đầu tiên (nhỏ).

[GC [PSYoungGen: 16448K->1616K(19136K)] 16448K->1624K(62848K), 0.0022134 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 

youngGen đi xuống bởi 14880K tuy nhiên fullHeap đi xuống bằng cách chỉ 14872K

Điều này có nghĩa 8k đã chuyển sang thế hệ nhiệm kỳ? Sự hiểu biết của tôi là GC có thể đã được gọi là một số instanced của lớp 'a' phải đã được đánh dấu còn sống và chuyển đến thế hệ nhiệm kỳ. Sự hiểu biết này có đúng không? Ngoài ra, đây có phải là "Floating Garbage" không? Làm thêm giờ các thế hệ nhiệm kỳ không được lấp đầy và yêu cầu fullGC, tuy nhiên phải mất một lúc.

Ngoài ra, trong trường hợp cụ thể này, không phải toàn bộ bộ sưu tập nhỏ được thu thập và lý tưởng không có gì xảy ra trong thế hệ quyền sở hữu? Tất cả đều là những vật thể sống ngắn.

Trả lời

2

Bạn đã có 1 thể hiện của Chuỗi còn sống khi GC đang được tiến hành (tham chiếu mạnh mẽ bên trong vòng lặp while) sao cho một trong số đó tồn tại do đó là 8k.

Trong trường hợp này, tôi sẽ không gọi cho chuỗi đổ rác nổi. Rác nổi là khi một đối tượng chưa sẵn sàng để được GC khi GC kiểm tra nó, nhưng đã sẵn sàng vào thời điểm GC kết thúc. Một ví dụ về điều đó sẽ là.

Thread1: Person p = new Person("sammy") 

    Thread2: gc runs and sees that the Person instance is reachable through p. 

Thread1: p = null; // This Person instance is now unreachable. 

    Thread2: GC finishes. The person instance could have been collected but was reachable at the time the collector checked it. 
0

Tôi không nghĩ rằng phép đo của bạn là chính xác.

Trước tiên, khi một GC xảy ra, Eden bị xóa và các vật thể sống sót trong không gian Survivor. Vì vậy, trong trường hợp của bạn, điều này giải thích lý do tại sao YoungGen đi từ 16448K đến 1616K: Những 1616K là số người sống sót.

Trong khi đó, tổng dung lượng heap sau GC là 1624K, có nghĩa là thế hệ cũ thực sự chứa 8K dữ liệu.

Thuật ngữ "Rác nổi" đề cập đến bộ sưu tập CMS, nơi các đối tượng mới chết không bị người thu thập bắt. Nó không áp dụng với ParallelGC.

Đối với trường hợp thử nghiệm của bạn, các đối tượng String sẽ không bao giờ xuất hiện trong Thế hệ cũ. Chúng sẽ tồn tại nhiều nhất 1 chu trình GC và chuyển đến một không gian Survivor, và sau đó sẽ được khai hoang

Hy vọng điều đó sẽ hữu ích!

+0

cảm ơn. nếu chuỗi các đối tượng không bao giờ đi vào thế hệ cũ, tại sao heap (chậm nhưng đều đặn) nhận được đầy đủ sau đó một GC đầy đủ được yêu cầu. Bạn nghĩ gì đang lấp đầy gen già của mình? –

+0

Có ít nhất 20 luồng khác đang chạy trong JVM, không chỉ là chuỗi "Chính" của bạn, do đó, nó khá hợp lý khi một số đối tượng được tạo. Ví dụ: các chủ đề Timer hoặc các chủ đề GC. Điều quan trọng là sau một GC đầy đủ, bạn đòi lại rất nhiều bộ nhớ. –

+0

@ N.M. Như một bên lề, lưu ý rằng Pierre nói rằng các đối tượng Strings trong ví dụ của bạn sẽ không đi vào gen cũ, không phải là các đối tượng chuỗi nói chung không bao giờ đi vào cũ. – monkjack