2011-07-19 9 views
41

Ứng dụng của tôi hiện đang tiêu thụ khá nhiều bộ nhớ vì nó đang chạy mô phỏng vật lý. Vấn đề là một cách nhất quán, ở mô phỏng thứ 51, java sẽ ném một lỗi thường là do một không gian heap ra khỏi bộ nhớ (chương trình của tôi cuối cùng chạy hàng ngàn mô phỏng).Vùng heap Java hết bộ nhớ

Có anyway tôi không thể chỉ tăng không gian heap nhưng sửa đổi chương trình của tôi để không gian heap được xóa sau mỗi lần chạy để tôi có thể chạy một số tùy ý của mô phỏng?

Cảm ơn

-edit-

Thanks guys. Hóa ra phần mềm giả lập không xóa thông tin sau mỗi lần chạy và tôi đã chạy những phần mềm đó trong một danh sách.

+6

nghe như rò rỉ bộ nhớ –

+2

Nếu khi bạn chạy nhiều mô phỏng hơn, bộ nhớ chân của bạn đang tăng, bạn bị rò rỉ bộ nhớ. Bạn cần phải tìm ra lý do tại sao bộ nhớ của bạn không được khai hoang ở phần cuối của một mô phỏng. – mjr

+0

Có, bộ nhớ bị rò rỉ có lẽ, tôi không nhớ tên, nhưng nó là một ứng dụng IBM cho phép bạn xem trực quan mọi luồng và ngăn xếp. Công cụ này giúp chúng tôi tìm ra vấn đề rò rỉ bộ nhớ với vài năm trước đây. sẽ cố gắng cập nhật cho bạn tên. – Cygnusx1

Trả lời

0

Java có nghĩa vụ phải xóa không gian heap cho bạn khi tất cả các đối tượng không còn được tham chiếu. Nó thường sẽ không phát hành nó trở lại hệ điều hành mặc dù, nó sẽ giữ cho bộ nhớ đó cho tái sử dụng nội bộ riêng của nó. Có thể kiểm tra xem bạn có một số mảng không bị xóa hay không.

2

Hãy thử thêm -Xmx để có thêm bộ nhớ (java -Xmx1024M YourClass) và đừng quên ngừng tham chiếu các biến mà bạn không cần nữa (rò rỉ bộ nhớ).

0

No. Heap được xóa bởi bộ thu gom rác bất cứ khi nào nó cảm thấy như vậy. Bạn có thể yêu cầu nó chạy (với System.gc()) nhưng nó không được bảo đảm để chạy.

Trước tiên hãy thử tăng bộ nhớ bằng cách thiết lập -Xmx256m

33

Không có cách nào để tăng động đống programatically từ đống được phân bổ khi Java Virtual Machine được bắt đầu.

Tuy nhiên, bạn có thể sử dụng lệnh này

java -Xmx1024M YourClass 

để thiết lập bộ nhớ 1024

hay, bạn có thể đặt một phút max

java -Xms256m -Xmx1024m YourClassNameHere 
+0

Nó không phải là một "* min *" nhưng tùy chọn bộ nhớ "** bắt đầu **" (do đó "s" trong cờ "ms") – McSonk

1

Bạn đang giữ tham chiếu đến biến bạn không còn cần (ví dụ: dữ liệu từ các mô phỏng trước đó)? Nếu có, bạn bị rò rỉ bộ nhớ. Bạn chỉ cần tìm nơi đang xảy ra và đảm bảo rằng bạn loại bỏ các tham chiếu đến các biến khi chúng không còn cần thiết nữa (điều này sẽ tự động xảy ra nếu chúng nằm ngoài phạm vi).

Nếu bạn thực sự cần tất cả dữ liệu đó từ các mô phỏng trước đó trong bộ nhớ, bạn cần phải tăng kích thước heap hoặc thay đổi thuật toán của mình.

11

Có nhiều công cụ mà bạn có thể sử dụng để giúp chẩn đoán sự cố này. JDK bao gồm JVisualVM sẽ cho phép bạn đính kèm vào quá trình đang chạy của bạn và hiển thị những đối tượng nào có thể không thể kiểm soát được. Netbeans có một wrapper xung quanh nó hoạt động khá tốt. Eclipse có Trình phân tích bộ nhớ Eclipse, cái mà tôi sử dụng thường xuyên nhất, dường như chỉ xử lý các tệp kết xuất lớn hơn một chút. Ngoài ra còn có một tùy chọn dòng lệnh, -XX:+HeapDumpOnOutOfMemoryError sẽ cung cấp cho bạn một tệp cơ bản là ảnh chụp nhanh bộ nhớ quy trình của bạn khi chương trình của bạn bị lỗi. Bạn có thể sử dụng bất kỳ công cụ được đề cập ở trên để xem xét nó, nó thực sự có thể giúp rất nhiều khi chẩn đoán các loại vấn đề.

Tùy thuộc vào mức độ hoạt động của chương trình, có thể là một trường hợp đơn giản của JVM không biết thời điểm thu thập rác thải tốt, bạn cũng có thể xem xét các tùy chọn thu gom rác song song.

+1

Không nên là -XX: + HeapDumpOnOutOfMemoryError (+ thay vì -) ? http://www.oracle.com/technetwork/java/javase/clopts-139448.html#gbzrr –

+0

Có thể, Đó là một trang khác, mặc dù tương tự từ cùng một công ty mà tôi đã sao chép văn bản của mình. Cảm ơn chỉnh sửa – mezmo

+0

liên kết JVisualVM cũng đã thay đổi thành: https://docs.oracle.com/javase/6/docs/technotes/guides/visualvm/intro.html –

16

Nếu bạn đang sử dụng nhiều bộ nhớ và bị rò rỉ bộ nhớ, bạn có thể kiểm tra xem bạn có đang sử dụng số lượng lớn ArrayList s hoặc HashMap s với nhiều thành phần không.

An ArrayList được triển khai dưới dạng dynamic array. Mã nguồn từ Sun/Oracle cho thấy khi một phần tử mới được chèn vào một ArrayList đầy đủ, một mảng mới gấp 1,5 lần kích thước của mảng ban đầu được tạo và các phần tử được sao chép lại. Điều này có nghĩa là bạn có thể lãng phí tới 50% không gian trong mỗi ArrayList mà bạn sử dụng, trừ khi bạn gọi phương thức trimToSize của nó. Hoặc vẫn tốt hơn, nếu bạn biết số lượng các phần tử bạn sẽ chèn trước khi tay, sau đó gọi hàm khởi tạo với công suất ban đầu làm đối số của nó.

Tôi không kiểm tra mã nguồn cho HashMap rất cẩn thận, nhưng ngay từ cái nhìn đầu tiên nó xuất hiện rằng chiều dài mảng trong mỗi HashMap phải là một sức mạnh của hai, làm cho nó thực hiện một mảng động. Lưu ý rằng HashSet về bản chất là một trình bao bọc xung quanh HashMap.

5

Tôi cũng phải đối mặt với cùng một vấn đề. Tôi đã giải quyết bằng cách thực hiện việc xây dựng bằng các bước như sau.

-> Nhấp chuột phải vào dự án chọn runas -> Run cấu hình

Chọn dự án của bạn như BaseDirectory. Thay cho mục tiêu cung cấp nhật thực: eclipse install

-> Trong tab thứ hai, hãy cung cấp -Xmx1024m làm đối số VM.

3

Tôi muốn thêm rằng sự cố này tương tự như rò rỉ bộ nhớ Java thông thường.

Khi bộ thu gom rác JVM không thể xóa bộ nhớ "lãng phí" của ứng dụng Java/Java EE của bạn theo thời gian, OutOfMemoryError: Java heap space sẽ là kết quả.

Điều quan trọng là để thực hiện một chẩn đoán đúng đầu tiên:

  • Enable verbose:gc. Điều này sẽ cho phép bạn hiểu mô hình phát triển bộ nhớ theo thời gian.
  • Tạo và phân tích JVM Heap Dump. Điều này sẽ cho phép bạn hiểu dấu chân bộ nhớ ứng dụng của bạn và xác định nguồn gốc của (các) rò rỉ bộ nhớ.
  • Bạn cũng có thể sử dụng trình thu thập dữ liệu Java và trình phân tích rò rỉ bộ nhớ thời gian chạy như Plumbr để giúp bạn thực hiện tác vụ này.