2011-08-28 50 views
17

Khi tôi chạy mã được đề cập dưới đây (sử dụng netbeans), kích thước phân bổ heap thay đổi trong một hình dạng sawtooth.I am gắn chụp từ jVisualVM trong đó cho thấy đồ thị heap được sử dụng trong một hình dạng sawtooth. "lol" n stdout.Tại sao đồ thị có hình răng cưa?

class one{ 
    static int i=0; 
    public static void main(String a[]){ 
     while(i<10){ 
      System.out.println("lol"); 
     } 
    } 
} 

enter image description here bất cứ ai có thể giải thích lý do đằng sau hình dạng của đồ thị của đống đã qua sử dụng?

ps: Đây xảy ra ngay cả khi tôi chạy nó mà không sử dụng NetBeans vì vậy nó được phần nào không liên quan đến netbeans ...

+1

Và dường như thay đổi tùy theo ... tốt ... 3 megabyte? Điều đó có thực sự đúng không? – Owen

+0

Bạn nhận được một số thông tin chi tiết về điều này bằng cách thử các thuật toán thu gom rác khác. Xem ở đây để biết thông tin: http://www.tikalk.com/java/garbage-collection-serial-vs-parallel-vs-concurrent-mark-sweep – skaffman

+3

@ buch11: không bao giờ đánh giá thấp lượng rác khổng lồ ngay cả Java tầm thường nhất phương thức/API có thể tạo. Tôi đã thực hiện tính toán khoa học đa luồng bằng cách sử dụng Java và tôi có thể nói với bạn rằng có rất nhiều gotchas thậm chí không buồn cười;) Bạn phải nhận ra rằng hầu hết các lập trình viên Java sẽ vui vẻ sử dụng những thứ như * Bản đồ * và cho bạn biết rằng nếu nó không phải là một nút cổ chai không có gì sai với nó. Java về cơ bản là một thế giới mà gần như tất cả mọi người tạo ra vô số chất thải và nghĩ rằng: * "Các nhà sưu tập rác sẽ chăm sóc nó" *. Có một lý do tại sao Photoshop không được viết bằng Java;) – SyntaxT3rr0r

Trả lời

23

Mô hình răng cưa trong việc sử dụng đống có thể được giải thích bằng thực tế là một số biến cục bộ được tạo trong khi gọi lời gọi System.out.println. Đáng chú ý nhất trong Oracle/Sun JRE, một số HeapCharBuffer trường hợp được tạo ra trong thế hệ trẻ, như đã nêu trong các bản chụp sau thu được bằng cách sử dụng profiler ký ức về VisualVM:

Visual VM - Memory snapshot

Bit thú vị là trong số các đối tượng trực tiếp hiện diện trên heap. Các mô hình răng cưa kết quả từ chu kỳ thu gom rác trẻ-gen xảy ra khi không gian eden đầy lên; vì không có hoạt động tính toán nặng được thực hiện trong chương trình, JVM có thể thực hiện một số lần lặp của vòng lặp, dẫn đến không gian eden (có kích thước 4MB) lấp đầy.Chu kỳ thu thập gen trẻ thành công sau đó xóa sạch phần lớn rác; nó gần như là luôn luôn toàn bộ không gian eden, trừ các đối tượng vẫn đang được sử dụng, như được chỉ ra bởi các dấu vết gc sau lấy từ VisualVM:

Visual VM GC probes

Hành vi của mô hình răng cưa do đó có thể được giải thích bởi một loạt các phân bổ đối tượng trong kế nhanh chóng lấp đầy không gian eden, kích hoạt một chu kỳ thu gom rác thải gen trẻ; quá trình này lặp lại theo chu kỳ mà không có sự chậm trễ vì quá trình JVM cơ bản không được preempted bởi một tiến trình khác, và luồng chính trong JVM chịu trách nhiệm phân bổ đối tượng cũng không được preempted bởi một luồng khác.

+0

Có điểm !!! – buch11

+0

Bạn được chào đón. Btw, tôi đã không nhận được sóng sawtooth hoàn hảo, như tôi giữ Alt-tabbing giữa VisualVM và Eclipse. Ảnh chụp màn hình của bạn mặt khác cho biết rằng bạn đã chạy VisualVM trong một thời gian khá dài. –

+0

thực sự tôi đã lập trình một cái gì đó mà làm cho sử dụng các chủ đề, đột nhiên mã đã đi vào loo vô hạn, tôi đã đi đến JVisualVM để kiểm tra xem các chủ đề đang chạy/ngủ/chờ đợi., Và sawtooth đến trước mặt tôi, cùng một lúc tôi nghĩ rằng đó là một cái gì đó liên quan đến chủ đề, nhưng sau đó đã cố gắng chạy mã trên và tất cả các câu đố bắt đầu từ đó chỉ ... vì vậy yay VisualVM của tôi đã chạy tất cả các thời gian. – buch11

1

Có rất nhiều nơi nó có thể đến từ, và nó có khả năng thực hiện phụ thuộc. Ít nhất sau đây là có thể (nhưng tất cả chỉ đơn thuần là đầu cơ)

  • đâu đó trong đống suối bên dưới System.out.println có một phân bổ mảng byte (cho rằng một trong những phương pháp cơ bản của một output stream là write (byte [] b, int off, int len))

  • nó overhead sử dụng bởi các phần mềm theo dõi bạn đang sử dụng (tôi đã không sử dụng nó)

  • đó là chi phí trong netbeans VM nơi nó kết thúc hiển thị đầu ra

5

Bất kỳ quá trình phân bổ đối tượng ở mức thông thường sẽ dẫn đến tăng mức tiêu thụ bộ nhớ heap, tiếp theo là giảm tức thì khi bộ thu gom rác thu thập các đối tượng không còn được sử dụng, dẫn đến hình dạng răng cưa đó. Trong trường hợp bạn tự hỏi tại sao quá trình java của bạn giữ bộ nhớ phân bổ trong khi ghi vào System.out, hãy nhớ rằng các chủ đề khác (ví dụ như một trong những bộ nhớ hiện tại thống kê để JVisualVM) có thể là những người phân bổ bộ nhớ.

1

Thực tế jVisualVM gây phân bổ đối tượng bổ sung. jVisualVM và jconsole đang sử dụng Java Management Extensions. Đính kèm ứng dụng đang chạy và yêu cầu các chỉ số JVM khiến các đối tượng bổ sung đó đang được tạo. Bạn có thể xác minh điều này bằng cách thêm vào cuộc gọi chương trình của mình tới

Runtime.getRuntime().freeMemory() 

báo cáo bộ nhớ trống trong vùng JVM. Nó sẽ hiển thị [hầu như] không có thay đổi bộ nhớ bằng cách chạy mã của bạn, nhưng ngay khi bạn kết nối jVisualVM với chương trình của bạn, bạn sẽ thấy mức sử dụng bộ nhớ tăng lên.

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