2015-09-08 17 views
28

Tôi đang chạy Eclipse 4.3 với một số Java 7 JRE. Khi tôi nâng cấp lên Java 8 JRE, Eclipse đột nhiên tiêu thụ nhiều bộ nhớ hơn. Nếu tôi khởi động Eclipse với JRE 7 trực tiếp vào không gian làm việc của tôi, nó phân bổ 600 MB RAM theo Task Manager. Khi tôi sử dụng JRE 8, giá trị này là 750 MB.Java 8 phân bổ quá nhiều bộ nhớ

Thậm chí tệ hơn, nếu tôi chạy một chương trình Java lớn thường phân bổ khoảng 10 GB RAM với JRE 7, chuyển sang JRE 8 làm cho nó phân bổ 12 GB RAM.

Có ai biết điều gì gây ra phân bổ RAM bổ sung này không? Tôi đã thử nghiệm tinh chỉnh tùy chọn khác nhau nhưng với không thành công:

-XX:ReservedCodeCacheSize= 
-XX:MaxMetaspaceSize= 
-XX:MetaspaceSize= 
... 
+3

số nào trong trình quản lý tác vụ bạn đang xem? – the8472

+0

Tại sao bạn nên nghĩ đến những tùy chọn đặc biệt này 'ReservedCodeCacheSize',' MaxMetaspaceSize' hoặc 'MetaspaceSize' là con đường để đi? Bạn đã kiểm tra xem những vùng bộ nhớ đặc biệt này có phải là nguyên nhân của mức tiêu thụ bộ nhớ cao hơn thay vì * kích thước heap thông thường * trước không? Bên cạnh đó, điểm Eclipse tiêu thụ 750 MB thay vì 600 MB là gì? Tôi thực sự hạnh phúc nếu Eclipse thực sự tiết kiệm trên máy tính của tôi ... – Holger

+4

thực sự, nhật thực của tôi thường dao động khoảng 2 GB RAM (tôi cần tăng giá trị mặc định) và các ứng dụng java sử dụng TEN GIGABYTES chắc chắn bị lỗi bởi thiết kế ; bạn không nên sử dụng một ứng dụng như vậy. Không có những thứ như "chương trình Java lớn", nếu bạn quản lý để có được kích thước JAR của bạn đáng chú ý cao hơn vài trăm MB bạn đã xây dựng các khung công tác ứng dụng lớn - Java thực sự hiệu quả về kích thước tệp, bạn sẽ không từng đạt tới hàng rào gigabyte trừ khi bạn làm sai. – specializt

Trả lời

9

Trong câu hỏi theo cách được hỏi

tại sao Java 8 phân bổ quá nhiều bộ nhớ trên máy tính của tôi

tôi không nghĩ rằng bất cứ ai sẽ có thể trả lời, tuy nhiên có một số hướng dẫn có thể giúp đỡ. Do bạn đang đo bộ nhớ thông qua trình quản lý tác vụ, bạn quan tâm đến tổng số RSS được sử dụng. Vì vậy,

  • Bước 1: Hãy so sánh giá trị mặc định JVM giữa phiên bản bạn đang chạy. Bạn có thể nhận được chúng bằng cách sử dụng lệnh java -XX:+UnlockDiagnosticVMOptions -XX:+PrintFlagsFinal -version cho cả hai jdks. Sử dụng sắp xếp văn bản trên đầu ra của bạn sẽ có thể có được một diff tốt đẹp bằng cách sử dụng bất kỳ công cụ so sánh. Những thứ như thay đổi collector GC mặc định và kích thước stack thread sẽ ảnh hưởng đến RSS cuối cùng rất nhiều.
  • Bước 2: Đo phân bổ cho từng nhóm bộ nhớ. Trong tổng số bộ nhớ chung được sử dụng bởi java có thể được tính bằng heap + metasize + code cache + native + (thread_stack_size * maximum_number_of_threads)
    • bộ nhớ Heap dễ dàng đo lường được (và có thể dễ dàng so sánh !!) bởi các công cụ trưởng thành (Eclipse Memory Analyzer, VisualVM, vv). Nếu bạn nhớ tăng diện tích heap - bạn rất may mắn. Trong vm trực quan bổ sung cho phép bạn cài đặt plugin sẽ hiển thị giá trị của tất cả các nhóm bộ nhớ có thể truy cập qua jmx.
    • metasize (aka permgen trong jdk < 8) nên nhiều hơn/ít hơn bằng nhau và có thể được tìm thấy với công cụ jmap. Không cần phải chơi cờ, bạn có thể nhận được số và chỉ cần so sánh bất cứ khi nào nó được tăng lên hay không.
    • Code cache: ngoài bộ nhớ cache mã dành riêng, bạn có thể đặt bộ nhớ cache mã ban đầu (và điều đó sẽ ảnh hưởng đến lượng RSS được sử dụng).
    • bản địa: đó là một chút cừu đen. Nếu tất cả các vùng nhớ khác đều bằng nhau (bộ nhớ của bạn là 2GB) bộ nhớ bị mất phải ở đâu đó trong vùng gốc. Công cụ duy nhất tôi biết là jcmd và công cụ này có tài liệu mở rộng trong tài liệu oracle.

Non kỹ thuật - trong khi tinh chỉnh tùy chọn khác nhau để giảm bộ nhớ có thể giúp đỡ, cơ hội của các giá trị đúng nhận được gần gũi với tìm kim trong đống cỏ khô. Tôi thực sự khuyên bạn nên có một cách về cách RSS được sử dụng trong java. Kiến thức này sẽ có ích trong một vài năm tới!

Vui lòng cho tôi biết bất cứ khi nào bạn muốn tham khảo cụ thể hơn hoặc giải thích rõ hơn. Và ...Chúc may mắn với nhiệm vụ của bạn ;-)

+0

Tôi không thấy tăng bộ nhớ heap và bộ nhớ metaspace khi so sánh JDK7 và JDK8 Tôi đã thực hiện các phép đo với ´jvisualvm´. Thiết lập ReservedCodeCacheSize trở lại 48 MB như là giá trị mặc định trong JRE7 chỉ có tác động tối thiểu.Đó là bộ nhớ riêng phát triển về kích thước. – RegedUser00x

+0

Có phải cả hai bit jdks 64 (hoặc 32) không? Hỏi vì bạn không chỉ định câu hỏi đó. –

+0

Có, tôi chỉ sử dụng 64 bit: JDK7 64 bit, JDK8 64 bit, JRE7 64 bit và JRE8 64 bit. – RegedUser00x

1

Tôi có thể xác nhận rằng ứng dụng web mà tôi đang làm việc (Jetty, Struts2, JDBC) tiêu thụ thêm khoảng 300 MB RAM (1.2G) ngay sau khi khởi động khi chạy trong JRE 1.8.0_72 so với JRE 1.7.0_80. Ứng dụng đang chạy trên Centos 6 x64 và để làm cho phép đo bộ nhớ càng trong suốt càng tốt, tôi đã vô hiệu hóa trao đổi và thiết lập -Xms bằng -Xmx (40% RAM có sẵn). Tôi đã sử dụng dstat --top-mem hoặc top -m để nhận tổng bộ nhớ được tiêu thụ bởi quá trình java.

Hơn nữa khi máy khách Web kết nối quá thường xuyên với ứng dụng, tổng bộ nhớ tiêu thụ tăng lên cho đến khi hệ thống hết bộ nhớ và tiêu diệt quá trình java. Chỉ những gì tôi có thể thấy là một thông tin trong/var/log/messages:

ngày 10 Tháng 11 21:29:54 hạt nhân của tôi: Hết bộ nhớ: Giết quá trình 26.610 (java) điểm 570 hoặc hy sinh con

Khi tôi chạy vòng lặp vô hạn từ bash gọi 4 máy khách Web song song kết nối với ứng dụng (= thiết lập kết nối TCP mới), yêu cầu trạng thái ứng dụng và ngắt kết nối thì tổng bộ nhớ được ứng dụng tiêu thụ tăng khoảng 100-200 KB mỗi phút. Mỗi khách hàng thực hiện 6-10 yêu cầu mỗi phút. Kích thước bộ nhớ heap đã sử dụng ổn định.

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