2017-09-19 30 views
5

An OutOfMemoryError xảy ra khi vùng heap không có đủ bộ nhớ để tạo đối tượng mới. Nếu heap không có đủ bộ nhớ, thì đối tượng OutOfMemoryError được tạo. Tôi đang cố gắng để hiểu điều này, xin vui lòng tư vấn cho.Đối tượng OutOfMemoryError được tạo ở đâu trong Java

+0

câu hỏi phỏng vấn tuyệt vời IMO - nhưng tôi đã thất bại. cảm ơn bạn đã đăng nó – Eugene

Trả lời

4

Nó được tạo ra bởi JVM, không bị giới hạn bởi -Xmx hoặc các tham số khác. Heap dành cho chương trình của bạn đã hết, không phải bộ nhớ có sẵn cho JVM.

+0

Cảm ơn bạn. Đây là một trong những câu hỏi phỏng vấn được hỏi với tôi trong một cuộc phỏng vấn. – manjosh

+0

Thực tế, [hơi phức tạp hơn] (https://stackoverflow.com/a/46298757/2711488)… – Holger

6

Tất nhiên, đây là hành vi phụ thuộc vào triển khai. HotSpot có một số bộ nhớ heap không thể truy cập được cho các phân bổ thông thường, JVM có thể sử dụng để xây dựng một OutOfMemoryError. Tuy nhiên, vì Java cho phép một số chủ đề tùy ý, một số chủ đề tùy ý có thể va vào tường cùng một lúc, vì vậy không có bảo đảm rằng bộ nhớ đủ để xây dựng một cá thể OutOfMemoryError riêng biệt cho mỗi bộ nhớ.

Vì vậy, trường hợp khẩn cấp OutOfMemoryError được tạo khi khởi động JVM tồn tại trong suốt toàn bộ phiên, để đảm bảo rằng lỗi có thể được ném ngay cả khi không còn bộ nhớ. Vì cá thể sẽ được chia sẻ cho tất cả các chuỗi gặp phải lỗi trong khi thực sự không còn bộ nhớ, bạn sẽ nhận ra tình trạng không liên quan này do thực tế là lỗi này sẽ không có dấu vết ngăn xếp.

Chương trình sau

ConcurrentHashMap<OutOfMemoryError,Integer> instances = new ConcurrentHashMap<>(); 

ExecutorService executor = Executors.newCachedThreadPool(); 
executor.invokeAll(Collections.nCopies(1000,() -> { 
      ArrayList<Object> list = new ArrayList<>(); 
      for(;;) try { 
       list.add(new int[10_000_000]); 
      } catch(OutOfMemoryError err) { 
       instances.merge(err, 1, Integer::sum); 
       return err; 
      } 
     })); 
executor.shutdown(); 
System.out.println(instances.size()+" distinct errors created"); 
instances.forEach((err,count) -> { 
    StackTraceElement[] trace = err.getStackTrace(); 
    System.out.println(err.getClass().getName()+"@"+Integer.toHexString(err.hashCode()) 
     +(trace!=null&&trace.length!=0? " has": " has no")+" stacktrace, used "+count+'x'); 
}); 

chạy dưới jdk1.8.0_65 với -Xmx100M và chờ đợi một nửa phút đã cho tôi

5 distinct errors created 
[email protected] has no stacktrace, used 996x 
[email protected] has stacktrace, used 1x 
[email protected] has stacktrace, used 1x 
[email protected] has stacktrace, used 1x 
[email protected] has stacktrace, used 1x 

cho thấy bộ nhớ dành riêng có thể phục vụ cho việc xây dựng bốn biệt OutOfMemoryError trường (bao gồm cả bộ nhớ cần thiết để ghi lại dấu vết ngăn xếp của chúng) trong khi tất cả các luồng khác phải quay trở lại phiên bản được chia sẻ dành riêng.

Tất nhiên, các con số có thể khác nhau giữa các môi trường khác nhau.

+0

rất thú vị, tôi không biết gì về điều này – Eugene

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