java.lang.OutOfMemoryError: Java heap space


96

Tôi gặp lỗi sau khi thực thi chương trình đa luồng

java.lang.OutOfMemoryError: Java heap space

Lỗi trên đã xảy ra ở một trong các chuỗi.

  1. Theo hiểu biết của tôi, không gian Heap chỉ bị chiếm bởi các biến cá thể. Nếu điều này là chính xác, thì tại sao lỗi này xảy ra sau khi chạy tốt đôi khi vì không gian cho các biến ví dụ được phân bổ tại thời điểm tạo đối tượng.

  2. Có cách nào để tăng không gian đống?

  3. Tôi nên thực hiện những thay đổi gì đối với chương trình của mình để Chương trình sẽ chiếm ít dung lượng hơn?


Câu trả lời:


104

Nếu bạn muốn tăng không gian heap của mình, bạn có thể sử dụng java -Xms<initial heap size> -Xmx<maximum heap size>trên dòng lệnh. Theo mặc định, các giá trị dựa trên phiên bản JRE và cấu hình hệ thống. Bạn có thể tìm hiểu thêm về các tùy chọn VM trên trang web Java .

Tuy nhiên, tôi khuyên bạn nên lập hồ sơ ứng dụng của mình để tìm hiểu lý do tại sao kích thước đống của bạn đang bị ăn mòn. NetBeans có một hồ sơ rất tốt đi kèm với nó. Tôi tin rằng nó sử dụng jvisualvmdưới mui xe. Với một hồ sơ, bạn có thể cố gắng tìm nơi nhiều đối tượng đang được tạo, khi nào các đối tượng được thu gom rác và hơn thế nữa.


1
Tôi đang sử dụng Netbeans nhưng tôi không biết cách sử dụng trình biên dịch. Tôi muốn biết thêm về hồ sơ để tôi có thể sử dụng nó để tìm lỗi bộ nhớ trong ứng dụng của mình.
Yatendra Goel

Tôi đã thêm một liên kết đến một trang trên trang NetBeans ( profiler.netbeans.org ) có tài liệu rất tốt về hồ sơ, từ những điều cơ bản đến nâng cao hơn.
Thomas Owens

Giá trị mặc định thay đổi với các phiên bản java, sẽ rất tốt nếu bạn đưa thông tin này vào câu trả lời.
Dariusz

Chỉ cần khắc phục sự cố tương tự và lần đầu tiên thử: java -jar sharing.jar -Xmx512m -Xms512m - điều này mang lại cho tôi lỗi tương tự nhưng khi tôi thực hiện như vậy: java -Xmx512m -Xms512m -jar sharing.jar - tất cả đều ổn. Vì vậy thứ tự của các tham số cũng rất quan trọng.
hipokito

@hipokito Đối số sau khi tệp jar được chuyển sang phương thức main () của tệp jar dưới dạng args []
Asu

29

1.- Có, nhưng nó đề cập khá nhiều đến toàn bộ bộ nhớ được chương trình của bạn sử dụng.

2.- Có, hãy xem các tùy chọn Java VM

-Xms<size>        set initial Java heap size
-Xmx<size>        set maximum Java heap size

I E

java -Xmx2g gán tối đa 2 gigabyte ram cho ứng dụng của bạn

Nhưng bạn nên xem nếu bạn không bị rò rỉ bộ nhớ trước.

3.- Nó phụ thuộc vào chương trình. Thử chỗ rò rỉ bộ nhớ. Câu hỏi này sẽ khó trả lời. Gần đây, bạn có thể lập hồ sơ bằng cách sử dụng JConsole để tìm hiểu xem bộ nhớ của bạn sẽ đi đến đâu


while which (true);)
Gal Bracha

8

Bạn có thể muốn xem trang web này để tìm hiểu thêm về bộ nhớ trong JVM: http://developer.streamezzo.com/content/learn/articles/optimization-heap-memory-usage

Tôi thấy hữu ích khi sử dụng visualgc để xem các phần khác nhau của mô hình bộ nhớ được lấp đầy như thế nào, để xác định những gì cần thay đổi.

Rất khó để xác định phần nào của bộ nhớ đã được lấp đầy, do đó visualgc, vì bạn có thể muốn chỉ thay đổi phần đang gặp sự cố, thay vì chỉ nói,

Khỏe! Tôi sẽ cung cấp 1G RAM cho JVM.

Cố gắng nói chính xác hơn về những gì bạn đang làm, về lâu dài có thể bạn sẽ thấy chương trình tốt hơn cho nó.

Để xác định vị trí rò rỉ bộ nhớ, bạn có thể sử dụng các bài kiểm tra đơn vị cho điều đó, bằng cách kiểm tra bộ nhớ trước khi kiểm tra và sau đó, và nếu có sự thay đổi quá lớn thì bạn có thể muốn kiểm tra nó, nhưng, bạn cần kiểm tra trong khi kiểm tra của bạn vẫn đang chạy.


6

Để tăng kích thước heap, bạn có thể sử dụng đối số -Xmx khi khởi động Java; ví dụ

-Xmx256M

6

Bạn có thể lấy kích thước bộ nhớ heap của mình thông qua chương trình bên dưới.

public class GetHeapSize {
    public static void main(String[] args) {
        long heapsize = Runtime.getRuntime().totalMemory();
        System.out.println("heapsize is :: " + heapsize);
    }
} 

sau đó, bạn cũng có thể tăng kích thước heap bằng cách sử dụng: java -Xmx2g http://www.oracle.com/technetwork/java/javase/tech/vmoptions-jsp-140102.html


6
  1. Theo hiểu biết của tôi, không gian Heap chỉ bị chiếm bởi các biến cá thể. Nếu điều này là chính xác, thì tại sao lỗi này xảy ra sau khi chạy tốt đôi khi vì không gian cho các biến ví dụ được phân bổ tại thời điểm tạo đối tượng.

Điều đó có nghĩa là bạn đang tạo nhiều đối tượng hơn trong ứng dụng của mình trong một khoảng thời gian liên tục. Các đối tượng mới sẽ được lưu trữ trong bộ nhớ heap và đó là lý do cho sự phát triển trong bộ nhớ heap.

Heap không chỉ chứa các biến cá thể. Nó sẽ lưu trữ tất cả các kiểu dữ liệu không nguyên thủy (Đối tượng). Thời gian tồn tại của các đối tượng này có thể ngắn (khối phương thức) hoặc dài (cho đến khi đối tượng được tham chiếu trong ứng dụng của bạn)

  1. Có cách nào để tăng không gian đống?

Đúng. Hãy xem bài báo oracle này để biết thêm chi tiết.

Có hai tham số để thiết lập kích thước heap:

-Xms:, đặt kích thước heap ban đầu và tối thiểu

-Xmx:, đặt kích thước đống tối đa

  1. Tôi nên thực hiện những thay đổi gì đối với chương trình của mình để Chương trình sẽ chiếm ít dung lượng hơn?

Nó phụ thuộc vào ứng dụng của bạn.

  1. Đặt bộ nhớ heap tối đa theo yêu cầu ứng dụng của bạn

  2. Không gây rò rỉ bộ nhớ trong ứng dụng của bạn

  3. Nếu bạn phát hiện thấy rò rỉ bộ nhớ trong ứng dụng của mình, hãy tìm nguyên nhân gốc rễ với sự trợ giúp của các công cụ cấu hình như MAT , Visual VM , jconsole , v.v. Khi bạn tìm ra nguyên nhân gốc rễ, hãy sửa lỗi rò rỉ.

Ghi chú quan trọng từ bài báo oracle

Nguyên nhân: Thông báo chi tiết Không gian heap Java cho biết không thể cấp phát đối tượng trong heap Java. Lỗi này không nhất thiết ám chỉ rò rỉ bộ nhớ.

Lý do có thể:

  1. Cấu hình không phù hợp (không phân bổ đủ bộ nhớ)
  2. Ứng dụng vô tình giữ các tham chiếu đến các đối tượng và điều này ngăn không cho các đối tượng được thu gom
  3. Các ứng dụng sử dụng quá nhiều trình hoàn thiện. Nếu một lớp có phương thức finalize, thì các đối tượng của kiểu đó sẽ không bị thu hồi dung lượng tại thời điểm thu gom rác. Nếu chuỗi trình hoàn thiện không thể theo kịp, với hàng đợi hoàn thiện, thì heap Java có thể đầy và loại ngoại lệ OutOfMemoryError này sẽ được ném ra .

Một lưu ý khác, hãy sử dụng các thuật toán thu gom rác tốt hơn ( CMS hoặc G1GC )

Hãy xem câu hỏi này để hiểu G1GC


5
  1. Trong hầu hết các trường hợp, mã không được tối ưu hóa. Giải phóng những đối tượng mà bạn cho rằng không cần thiết nữa. Tránh tạo các đối tượng trong vòng lặp của bạn mỗi lần. Cố gắng sử dụng bộ nhớ đệm. Tôi không biết ứng dụng của bạn đang hoạt động như thế nào. Nhưng trong lập trình, một quy tắc của cuộc sống bình thường cũng được áp dụng

    Phòng bệnh hơn chữa bệnh. "Đừng tạo các đối tượng không cần thiết"


3
  1. Các biến cục bộ nằm trên ngăn xếp. Không gian đống bị chiếm bởi các đối tượng.

  2. Bạn có thể sử dụng -Xmxtùy chọn.

  3. Về cơ bản, không gian heap được sử dụng hết mỗi khi bạn cấp phát một đối tượng mới newvà giải phóng một thời gian sau khi đối tượng không còn được tham chiếu nữa. Vì vậy, hãy đảm bảo rằng bạn không giữ các tham chiếu đến các đối tượng mà bạn không cần nữa.


1

Không, tôi nghĩ bạn đang nghĩ đến không gian ngăn xếp. Không gian đống bị chiếm bởi các đối tượng. Cách để tăng nó là -Xmx256m, thay thế 256 bằng số tiền bạn cần trên dòng lệnh.


1

Để tránh ngoại lệ đó, nếu bạn đang sử dụng JUnit và Spring, hãy thử thêm cái này vào mọi lớp thử nghiệm:

@DirtiesContext(classMode = DirtiesContext.ClassMode.AFTER_CLASS)

0

Trong netbeans, đi tới thanh công cụ 'Chạy', -> 'Đặt cấu hình dự án' -> 'Tùy chỉnh' -> 'chạy' của windo bật lên -> 'Tùy chọn VM' -> điền vào '-Xms2048m -Xmx2048m '. Nó có thể giải quyết vấn đề kích thước đống.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.