Strings là vấn đề
Về cơ bản trong Java, tài liệu tham khảo String
(điều mà sử dụng char[]
đằng sau hậu trường) sẽ thống trị hầu hết kinh doanh bộ nhớ ứng dụng khôn ngoan. Cách chúng được tạo ra xác định lượng bộ nhớ mà chúng tiêu thụ trong JVM.
Chỉ vì chúng rất cơ bản đối với hầu hết các ứng dụng kinh doanh dưới dạng kiểu dữ liệu và chúng cũng là một trong những bộ nhớ đói nhất. Đây không chỉ là một điều Java, String
các kiểu dữ liệu chiếm nhiều bộ nhớ trong nhiều ngôn ngữ và thư viện thời gian chạy, bởi vì ít nhất chúng chỉ là mảng 1 byte cho mỗi ký tự hoặc tệ hơn (Unicode) chúng là mảng nhiều byte cho mỗi ký tự.
Một lần khi profiling sử dụng CPU trên một ứng dụng web mà cũng đã có một sự phụ thuộc Oracle JDBC tôi phát hiện ra rằng StringBuffer.append()
thống trị chu kỳ CPU của nhiều bậc độ lớn hơn tất cả các phương pháp khác gọi kết hợp, ít hơn nhiều bất kỳ cuộc gọi phương pháp nào khác. Trình điều khiển JDBC đã thực hiện rất nhiều thao tác String
, loại bỏ giao dịch sử dụng PreparedStatements
cho mọi thứ.
gì bạn lo lắng về bạn không thể kiểm soát, không trực tiếp nào
Những gì bạn nên tập trung vào những gì là trong kiểm soát của bạn, mà là đảm bảo bạn không giữ cho tài liệu tham khảo dài hơn bạn cần, và rằng bạn không sao chép mọi thứ một cách không cần thiết. Các thói quen thu gom rác trong Java được tối ưu hóa cao và nếu bạn học cách các thuật toán của chúng hoạt động, bạn có thể đảm bảo chương trình của bạn hoạt động theo cách tối ưu để các thuật toán đó hoạt động.
Java Heap Memory không thích bằng tay quản lý bộ nhớ bằng các ngôn ngữ khác, những quy tắc không áp dụng
gì được coi là bộ nhớ rò rỉ bằng ngôn ngữ khác không phải là điều tương tự/nguyên nhân gốc rễ là trong Java với hệ thống thu gom rác của nó.
Rất có thể trong bộ nhớ Java không bị tiêu thụ bởi một đối tượng uber duy nhất bị rò rỉ (tham chiếu lơ lửng trong các môi trường khác).
Đó là hầu hết rất nhiều khả năng phân bổ nhỏ hơn vì StringBuffer
/StringBuilder
đối tượng không có kích thước thích hợp trên instantantations đầu tiên và sau đó phải tự động phát triển các char[]
mảng tổ chức tiếp theo append()
cuộc gọi.
Các đối tượng trung gian này có thể được giữ lâu hơn dự kiến bởi bộ thu gom rác vì phạm vi của chúng và rất nhiều thứ khác có thể thay đổi theo thời gian chạy.
VÍ DỤ: bộ thu gom rác thải có thể quyết định có ứng cử viên, nhưng vì nó cho rằng vẫn còn nhiều thời gian để tiết kiệm thời gian, và nó sẽ đợi cho đến khi áp lực bộ nhớ tăng lên.
Bộ thu gom rác thực sự tốt ngay bây giờ, nhưng nó không phải là ma thuật, nếu bạn đang làm những điều thoái hóa, nó sẽ làm cho nó không hoạt động tối ưu. Có rất nhiều tài liệu trên internet về cài đặt bộ thu gom rác cho tất cả các phiên bản của JVM.
Các đối tượng không được tham chiếu này có thể không đạt đến thời gian mà bộ thu gom rác cho rằng cần phải xóa chúng khỏi bộ nhớ, hoặc có thể tham chiếu đến chúng do một số đối tượng khác nắm giữ (List
) mà bạn không nhận ra vẫn chỉ vào đối tượng đó. Đây là điều thường được gọi là rò rỉ trong Java, một lỗ hổng tham chiếu cụ thể hơn.
VÍ DỤ: Nếu bạn biết bạn cần phải xây dựng một 4K String
sử dụng một StringBuilder
tạo ra nó với new StringBuilder(4096);
không phải là mặc định, mà là giống như 32 và ngay lập tức sẽ bắt đầu tạo rác có thể đại diện cho nhiều lần những gì bạn nghĩ đối tượng nên được kích thước khôn ngoan.
Bạn có thể khám phá xem có bao nhiêu loại đối tượng được khởi tạo với VisualVM, điều này sẽ cho bạn biết những gì bạn cần biết. Sẽ không có một ánh sáng nhấp nháy lớn chỉ vào một trường hợp duy nhất của một lớp duy nhất nói rằng, "Đây là người tiêu dùng bộ nhớ lớn!", Đó là trừ khi chỉ có một trường hợp của một số char[]
mà bạn đang đọc một số tập tin lớn vào, và điều này là không thể, bởi vì nhiều lớp khác sử dụng char[]
nội bộ; và sau đó bạn đã biết khá nhiều rồi.
Tôi không thấy bất kỳ đề cập đến OutOfMemoryError
Bạn có lẽ không có một vấn đề trong mã của bạn, hệ thống thu gom rác thải chỉ có thể không được bị đặt dưới áp lực đủ để kick vào và đối tượng deallocate rằng bạn nghĩ rằng nó nên được dọn dẹp. Điều gì bạn nghĩ rằng là một vấn đề có thể không phải là, không trừ khi chương trình của bạn bị lỗi với OutOfMemoryError
.Đây không phải là C, C++, Objective-C hoặc bất kỳ ngôn ngữ/thời gian chạy bộ nhớ thủ công nào khác. Bạn không thể quyết định cái gì có trong bộ nhớ hay không ở mức độ chi tiết mà bạn mong đợi bạn sẽ có thể.
Tôi sử dụng một trình hồ sơ hiển thị cho tôi đối tượng cũng đang được phân bổ. Tôi không biết nếu VisualVM có thể làm điều này, nhưng nó rất hữu ích. Cái mà tôi sử dụng là YourKit, nhưng nó không miễn phí (nhưng bạn có thể lấy giấy phép eval) –
@PeterLawrey Tôi thực sự đã đọc câu trả lời bạn đã viết trước đây, nơi bạn đã đề cập đến bộ nhớ của mình là lựa chọn đầu tiên của bạn vì lời khuyên của bạn luôn tuyệt vời) nhưng có một chút tốn kém và tôi chỉ đang học. –
mà không sử dụng một cái gì đó mà cụ mã của bạn không có phân tích sẽ có thể chỉ ra ví dụ == những gì bạn gọi là một tài liệu tham khảo trong nguồn của bạn. –