“Java.lang.OutOfMemoryError: không thể tạo chuỗi gốc mới”


124

Chúng tôi đang nhận được "java.lang.OutOfMemoryError : unable to create new native Thread"trên máy ảo RAM 8GB sau 32k luồng (ps -eLF | grep -c java)

Tuy nhiên "top" and "free -m" shows 50% free memory available,. JDk là 64 bit và đã thử với cả HotSpot và JRockit .erver có Linux 2.6.18

Chúng tôi cũng đã thử OS stack size (ulimit -s)tinh chỉnh và giới hạn quy trình tối đa (ulimit -u), tăng limit.conf nhưng tất cả đều vô ích.

Ngoài ra, chúng tôi đã thử gần như tất cả các kết hợp kích thước đống có thể có, giữ cho nó thấp, cao, v.v.

Tập lệnh chúng tôi sử dụng để chạy ứng dụng là

/opt/jrockit-jdk1.6/bin/java -Xms512m -Xmx512m -Xss128k -jar JavaNatSimulator.jar /opt/tools/jnatclients/natSimulator.properties

Cảm ơn vi đa trả lơi.

Chúng tôi đã thử chỉnh sửa /etc/security/limits.conf và ulimit nhưng vẫn vậy

[root@jboss02 ~]# ulimit -a
core file size          (blocks, -c) 0
data seg size           (kbytes, -d) unlimited
scheduling priority             (-e) 0
file size               (blocks, -f) unlimited
pending signals                 (-i) 72192
max locked memory       (kbytes, -l) 32
max memory size         (kbytes, -m) unlimited
open files                      (-n) 65535
pipe size            (512 bytes, -p) 8
POSIX message queues     (bytes, -q) 819200
real-time priority              (-r) 0
stack size              (kbytes, -s) 10240
cpu time               (seconds, -t) unlimited
max user processes              (-u) 72192
virtual memory          (kbytes, -v) unlimited
file locks                      (-x) unlimited

11
Hệ điều hành có giới hạn về số luồng mà bạn có thể tạo. Tại sao bạn tạo hơn 32k chủ đề? Hệ thống của bạn rất có thể không có hàng nghìn lõi xử lý, việc tạo ra quá nhiều luồng là không hữu ích. Sử dụng một nhóm chủ đề ( ExecutorService) để thay thế.
Jesper

Cảm ơn vi đa trả lơi. Chúng tôi đang sử dụng một thư viện mã nguồn mở và cố gắng tải thử nghiệm đó. Bất kỳ thư viện mã nguồn mở nào cũng đang tạo ra rất nhiều luồng. Nhưng những gì tôi không hiểu, là khi "trên cùng" hiển thị 50% bộ nhớ trống thì tại sao OutOfMemory Error.
Deepak Tewani

Thư viện mã nguồn mở mà chúng tôi đang sử dụng trong Thư viện ICE4j
Deepak Tewani

11
OutOfMemoryError không nhất thiết có nghĩa là không gian heap hoặc RAM "chung" đã cạn kiệt. Trong trường hợp này, rõ ràng lỗi là do hệ điều hành không có tài nguyên để phân bổ một luồng bổ sung. Có 50% bộ nhớ trống không liên quan đến lỗi cụ thể này.
Andrzej Doyle

1
Các tài nguyên khác cần thiết để tạo luồng mới là gì. Chúng tôi có ấn tượng rằng nếu chúng tôi tăng RAM, thì chúng tôi có thể tạo ra nhiều luồng hơn. Vui lòng hướng dẫn chúng tôi
Deepak Tewani

Câu trả lời:


80

Đây không phải là vấn đề bộ nhớ mặc dù tên ngoại lệ rất gợi ý như vậy, mà là vấn đề tài nguyên hệ điều hành. Bạn sắp hết luồng gốc, tức là hệ điều hành sẽ cho phép JVM của bạn sử dụng bao nhiêu luồng.

Đây là một vấn đề không phổ biến, bởi vì bạn hiếm khi cần nhiều như vậy. Bạn có rất nhiều chủ đề sinh sản vô điều kiện mà các chủ đề nên nhưng không kết thúc?

Bạn có thể cân nhắc việc viết lại sử dụng Callable / Runnables dưới sự kiểm soát của Người thực thi nếu có thể. Có rất nhiều trình thực thi tiêu chuẩn với các hành vi khác nhau mà mã của bạn có thể dễ dàng kiểm soát.

(Có nhiều lý do tại sao số lượng luồng bị hạn chế, nhưng chúng khác nhau giữa các hệ điều hành và hệ điều hành)


Cảm ơn vi đa trả lơi. Chúng tôi đang sử dụng thư viện mã nguồn mở ICE4j và cố gắng tải thử nghiệm đó. Chúng tôi không thể tăng giới hạn luồng trong hệ điều hành khi chúng tôi biết rằng máy chủ còn 50% bộ nhớ.
Deepak Tewani

Có thể, nhưng tôi nghĩ rằng nó sẽ không giúp bạn như vậy. Nếu bạn hết tài nguyên khi thử nghiệm tải, bạn cần có khả năng kiểm soát những gì xảy ra trong ứng dụng của mình. Tại sao bạn có 32000 chủ đề hoạt động cùng một lúc?
Thorbjørn Ravn Andersen

Chúng tôi đang tạo máy khách 11K sử dụng 32 luồng K để đọc, ghi dữ liệu trên các ổ cắm UDP. Trong số những 32 K đề, 10K chủ đề được giữ đề còn sống được sử dụng để giữ cho các ổ cắm mở
Deepak Tewani

Tôi tin rằng vấn đề này được giải quyết trong các máy chủ web hiện đại. Ngoài ra udp có thể mất gói tin - bất kỳ lý do gì bạn không chỉ sử dụng một máy chủ web?
Thorbjørn Ravn Andersen

7
Vì ngoại lệ OutOfMemory nên được đặt tên là OutOfResources. Hệ điều hành không thể cung cấp tài nguyên bạn cần. (Và hóa ra tôi không biết ice4j)
Thorbjørn Ravn Andersen

14

Tôi gặp phải sự cố tương tự trong quá trình kiểm tra tải, lý do là vì JVM không thể tạo thêm một chuỗi Java mới. Dưới đây là mã nguồn JVM

if (native_thread->osthread() == NULL) {    
// No one should hold a reference to the 'native_thread'.    
    delete native_thread;   
if (JvmtiExport::should_post_resource_exhausted()) {      
    JvmtiExport::post_resource_exhausted(        
        JVMTI_RESOURCE_EXHAUSTED_OOM_ERROR | 
        JVMTI_RESOURCE_EXHAUSTED_THREADS, 
        "unable to create new native thread");    
    } THROW_MSG(vmSymbols::java_lang_OutOfMemoryError(), "unable to create new native thread");  
} Thread::start(native_thread);`

Nguyên nhân gốc rễ: JVM ném ngoại lệ này khi JVMTI_RESOURCE_EXHAUSTED_OOM_ERROR (tài nguyên cạn kiệt (có nghĩa là bộ nhớ hết)) hoặc JVMTI_RESOURCE_EXHAUSTED_THREADS (Chủ đề đã cạn kiệt).

Trong trường hợp của tôi, Jboss đang tạo quá nhiều luồng để phục vụ yêu cầu, nhưng tất cả các luồng đều bị chặn. Vì điều này, JVM cạn kiệt với các luồng cũng như với bộ nhớ (mỗi luồng giữ bộ nhớ, không được giải phóng, vì mỗi luồng bị chặn).

Đã phân tích các bãi chứa luồng java quan sát thấy gần 61K luồng bị chặn bởi một trong các phương pháp của chúng tôi, gây ra sự cố này. Dưới đây là phần của kết xuất Chủ đề

"SimpleAsyncTaskExecutor-16562" #38070 prio=5 os_prio=0 tid=0x00007f9985440000 nid=0x2ca6 waiting for monitor entry [0x00007f9d58c2d000]
   java.lang.Thread.State: BLOCKED (on object monitor)

Phương pháp chặn như thế nào? Không bao giờ trở lại?
Thorbjørn Ravn Andersen

8

Có khả năng là hệ điều hành của bạn không cho phép số lượng luồng bạn đang cố tạo hoặc bạn đang đạt đến một số giới hạn trong JVM. Đặc biệt nếu đó là một con số tròn như 32k, thì giới hạn của loại này hay loại khác là một thủ phạm rất có thể xảy ra.

Bạn có chắc mình thực sự cần 32k luồng không? Hầu hết các ngôn ngữ hiện đại đều có một số loại hỗ trợ cho các nhóm luồng có thể tái sử dụng - tôi chắc chắn rằng Java cũng có một số thứ (như ExecutorServicengười dùng Jesper đã đề cập). Có lẽ bạn có thể yêu cầu các chuỗi từ một nhóm như vậy, thay vì tạo các chuỗi mới theo cách thủ công.


1
Cảm ơn bạn đã trả lời Chúng tôi đang sử dụng thư viện mã nguồn mở ICE4j và đang cố gắng tải thử nghiệm đó. Chúng tôi không thể tăng giới hạn luồng trong OS khi biết rằng máy chủ còn 50% bộ nhớ.
Deepak Tewani

1
Chúng tôi đang tạo máy khách 11K sử dụng 32 luồng K để đọc, ghi dữ liệu trên các ổ cắm UDP. Trong số những 32 K đề, 10K chủ đề được giữ đề còn sống được sử dụng để giữ cho các ổ cắm mở
Deepak Tewani

7

Tôi cũng khuyên bạn nên xem thêm Kích thước ngăn xếp luồng và xem liệu bạn có tạo được nhiều luồng hơn không. Kích thước ngăn xếp chủ đề mặc định cho JRockit 1.5 / 1.6 là 1 MB cho máy ảo 64-bit trên hệ điều hành Linux. Các luồng 32K sẽ yêu cầu một lượng lớn bộ nhớ vật lý và ảo để đáp ứng yêu cầu này.

Hãy thử giảm Kích thước ngăn xếp xuống 512 KB như một điểm khởi đầu và xem liệu nó có giúp tạo nhiều luồng hơn cho ứng dụng của bạn hay không. Tôi cũng khuyên bạn nên khám phá quy mô theo chiều ngang, ví dụ như chia nhỏ quá trình xử lý ứng dụng của bạn trên nhiều máy vật lý hoặc máy ảo hơn.

Khi sử dụng máy ảo 64-bit, giới hạn thực sự sẽ phụ thuộc vào tính khả dụng của bộ nhớ vật lý và ảo của hệ điều hành và các tham số điều chỉnh hệ điều hành như ulimitc. Tôi cũng giới thiệu bài viết sau để tham khảo:

OutOfMemoryError: không thể tạo chuỗi gốc mới - Sự cố được phân cấp


5

Nếu jvm được khởi động thông qua systemd, có thể có maxTasks cho mỗi giới hạn quy trình (nhiệm vụ thực sự có nghĩa là luồng) trong một số hệ điều hành linux.

Bạn có thể kiểm tra điều này bằng cách chạy "trạng thái dịch vụ" và kiểm tra xem có giới hạn maxTasks hay không. Nếu có, bạn có thể xóa nó bằng cách chỉnh sửa /etc/systemd/system.conf, thêm cấu hình: DefaultTasksMax = infinity


3

Tôi đã gặp vấn đề tương tự do các quy trình ma không hiển thị khi sử dụng top in bash. Điều này ngăn JVM tạo ra nhiều luồng hơn.

Đối với tôi, nó đã giải quyết khi liệt kê tất cả các quy trình java với jps (chỉ thực thi jpstrong trình bao của bạn) và giết chúng một cách riêng biệt bằng cách sử dụngkill -9 pid lệnh bash cho mỗi quy trình ma.

Điều này có thể hữu ích trong một số trường hợp.


2

Bạn có cơ hội đối mặt với java.lang.OutOfMemoryError: Unable to create new native threadbất cứ khi nào JVM yêu cầu một luồng mới từ Hệ điều hành. Bất cứ khi nào hệ điều hành cơ bản không thể cấp phát một luồng gốc mới, OutOfMemoryError này sẽ được ném ra. Giới hạn chính xác cho các chủ đề gốc rất phụ thuộc vào nền tảng, do đó, khuyến nghị của nó là tìm ra các giới hạn đó bằng cách chạy thử nghiệm tương tự như ví dụ liên kết dưới đây. Tuy nhiên, nhìn chung, tình huống gây ra java.lang.OutOfMemoryError: Unable to create new native threadtrải qua các giai đoạn sau:

  1. Một luồng Java mới được yêu cầu bởi một ứng dụng chạy bên trong JVM
  2. Mã gốc JVM ủy quyền yêu cầu tạo một tiểu trình gốc mới cho hệ điều hành Hệ điều hành cố gắng tạo một tiểu trình gốc mới yêu cầu bộ nhớ được cấp cho tiểu trình
  3. Hệ điều hành sẽ từ chối cấp phát bộ nhớ gốc vì kích thước quy trình Java 32-bit đã làm cạn không gian địa chỉ bộ nhớ của nó - ví dụ: giới hạn kích thước quy trình (2-4) GB đã đạt - hoặc bộ nhớ ảo của hệ điều hành đã hết hoàn toàn
  4. Lỗi java.lang.OutOfMemoryError: Không thể tạo lỗi luồng gốc mới được ném ra.

Tham khảo: https://plumbr.eu/outofmemoryerror/unable-to-create-new-native-thread


2

Để biết quy trình nào đang tạo chuỗi, hãy thử:

ps huH

Tôi thường chuyển hướng đầu ra đến một tệp và phân tích tệp ngoại tuyến (số luồng cho mỗi quy trình có như mong đợi hay không)


1

Nếu Công việc của bạn không thành công do OutOfMemmory trên các nút, bạn có thể kiểm tra số lượng bản đồ và bộ giảm tốc tối đa của mình cũng như lựa chọn JVM cho mỗi nút. mapred.child.java.opts (mặc định là 200Xmx) thường phải được tăng lên dựa trên phần cứng cụ thể của các nút dữ liệu của bạn.

Liên kết này có thể hữu ích ... xin vui lòng kiểm tra


1
Tất cả chúng tôi đều đã thử thay đổi được đưa ra trên liên kết đó. Nhưng kết quả là như nhau :(
Deepak Tewani

1

cấu hình JBoss của bạn có một số vấn đề, /opt/jrockit-jdk1.6/bin/java -Xms512m -Xmx512m Xms và Xmx đang giới hạn mức sử dụng bộ nhớ JBoss của bạn đối với giá trị đã định cấu hình, vì vậy từ 8Gb, bạn có máy chủ chỉ sử dụng 512M + một số bổ sung cho mục đích riêng của anh ấy, hãy tăng con số đó lên, hãy nhớ để lại một số miễn phí cho hệ điều hành và những thứ khác đang chạy ở đó và có thể bạn sẽ làm cho nó chạy bất chấp mã không có mùi. Sửa mã cũng sẽ rất hay, nếu bạn có thể.


1

Lỗi này có thể xuất hiện vì hai lý do sau:

  • Không có chỗ trong bộ nhớ để chứa các chủ đề mới.

  • Số luồng vượt quá giới hạn Hệ điều hành.

Tôi nghi ngờ rằng số luồng đó đã vượt quá giới hạn cho quy trình java

Vì vậy, rất có thể vấn đề là do bộ nhớ Một điểm cần xem xét là

luồng không được tạo trong JVM heap. Chúng được tạo bên ngoài đống JVM. Vì vậy, nếu RAM còn ít chỗ trống hơn, sau khi phân bổ heap JVM, ứng dụng sẽ chạy vào “java.lang.OutOfMemoryError: không thể tạo luồng gốc mới”.

Giải pháp khả thi là giảm bộ nhớ heap hoặc tăng kích thước ram tổng thể


0

Tôi cũng gặp sự cố này và hóa ra là do sử dụng API java không đúng cách. Tôi đang khởi tạo trình tạo trong một phương pháp xử lý hàng loạt mà không được khởi chạy nhiều lần.

Về cơ bản tôi đã làm một cái gì đó như:

for (batch in batches) {
    process_batch(batch)
}

def process_batch(batch) {
    var client = TransportClient.builder().build()
    client.processList(batch)
}

khi đáng lẽ tôi nên làm điều này:

for (batch in batches) {
    var client = TransportClient.builder().build()
    process_batch(batch, client)
}

def process_batch(batch, client) {
    client.processList(batch)
}

-4

Trước hết, tôi sẽ không đổ lỗi nhiều như vậy cho OS / VM .. thay vì nhà phát triển đã viết mã tạo ra quá nhiều Chủ đề . Về cơ bản ở đâu đó trong mã của bạn (hoặc bên thứ 3) rất nhiều luồng được tạo ra mà không có sự kiểm soát .

Xem xét cẩn thận các chuỗi / mã ngăn xếp và kiểm soát số luồng được tạo. Thông thường, ứng dụng của bạn không cần một lượng lớn luồng, nếu có thì đó là một vấn đề khác.


10
Đây không phải là một giải pháp cho câu hỏi.
ftrujillo
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.