2011-10-08 29 views
7

Tóm tắt câu hỏi cơ bản là: Làm cách nào để tối ưu hóa phân bổ bộ nhớ tốt nhất của tôi để cung cấp nhiều bộ nhớ cho các DLL tôi truy cập thông qua JNI nhất có thể? Tôi nên nhắm mục tiêu gì để giảm thiểu, tôi nên nhắm mục tiêu gì để tối đa hóa, v.v.Ứng dụng Java gọi C++ DLL qua JNI; cách tốt nhất để cấp phát bộ nhớ?

SYSTEM: Chạy JBoss 6 dưới dạng dịch vụ Windows 32 trong hệ thống 32 bit có RAM 4 GB. Tôi hiểu rằng có những hạn chế tối đa đối với bộ nhớ cho Java Heap. JVM là JRE1.6.0_26

DỊCH VỤ: Cài đặt dưới JBoss là một ứng dụng web nhận được yêu cầu từ khách hàng; mỗi yêu cầu gọi C++ - được xây dựng DLL thông qua JNI để xử lý một tập tin hình ảnh trong một số thời trang hay khác.

ISSUE: Thỉnh thoảng, với hình ảnh nén lớn hơn hoặc một số (không phải tất cả) LZW, lớp java gọi sẽ nhận được thông báo rằng DLL gặp phải tình trạng cạn kiệt bộ nhớ toàn cầu và không hoàn tất quá trình được yêu cầu.

Không có gì khác đang hoạt động trên máy chủ ngoài các quy trình cửa sổ cơ bản.

thiết lập

hiện JBOSS App bộ nhớ máy chủ như sau, nhưng có thể quá mức:

-Xms1024m -Xmx1024m -Xss1024k -XX: MaxPermSize = 128

Tôi cố gắng để xác định các thiết lập bộ nhớ tốt nhất để cung cấp cho càng nhiều tài nguyên cho DLL JNI, vì tôi hiểu JNI không sử dụng bất kỳ bộ nhớ nào được cấp phát cho Heap Java.

Tôi đã đọc này, nhưng không tìm thấy chúng hữu ích để trả lời câu hỏi của tôi:

Java JNI : Memory allocation/partitioning

Can jconsole be used to identify memory leaks in JNI C++ objects?

Hai câu trả lời hiện đang cung cấp không giải quyết được câu hỏi inherient.

bộ nhớ hiện tại của máy chủ JBoss sau một tuần với JVM params thiết lập như trên (TaskManager chỉ ra quá trình java.exe tại 750,672k)

Total Memory Pools: 5 

Pool: Code Cache (Non-heap memory) 

    Peak Usage : init:2359296, used:7317312, committed:7438336, max:50331648 
    Current Usage : init:2359296, used:7306496, committed:7438336, max:50331648 


     |---------| committed:7.09Mb 
     +---------------------------------------------------------------------+ 
     |/////////| | max:48Mb 
     +---------------------------------------------------------------------+ 
     |---------| used:6.97Mb 


Pool: PS Eden Space (Heap memory) 

    Peak Usage : init:268500992, used:354811904, committed:354811904, max:355991552 
    Current Usage : init:268500992, used:270153472, committed:354091008, max:354156544 


     |--------------------------------------------------------------------| committed:337.69Mb 
     +---------------------------------------------------------------------+ 
     |///////////////////////////////////////////////////// || max:337.75Mb 
     +---------------------------------------------------------------------+ 
     |----------------------------------------------------| used:257.64Mb 


Pool: PS Survivor Space (Heap memory) 

    Peak Usage : init:44695552, used:44694896, committed:78643200, max:78643200 
    Current Usage : init:44695552, used:0, committed:1835008, max:1835008 


     |---------------------------------------------------------------------| committed:1.75Mb 
     +---------------------------------------------------------------------+ 
     | | max:1.75Mb 
     +---------------------------------------------------------------------+ 
     | used:0b 


Pool: PS Old Gen (Heap memory) 

    Peak Usage : init:715849728, used:123671968, committed:715849728, max:715849728 
    Current Usage : init:715849728, used:104048648, committed:715849728, max:715849728 


     |---------------------------------------------------------------------| committed:682.69Mb 
     +---------------------------------------------------------------------+ 
     |////////// | max:682.69Mb 
     +---------------------------------------------------------------------+ 
     |---------| used:99.23Mb 


Pool: PS Perm Gen (Non-heap memory) 

    Peak Usage : init:16777216, used:91989664, committed:134217728, max:134217728 
    Current Usage : init:16777216, used:90956472, committed:90963968, max:134217728 


     |----------------------------------------------| committed:86.75Mb 
     +---------------------------------------------------------------------+ 
     |//////////////////////////////////////////////| | max:128Mb 
     +---------------------------------------------------------------------+ 
     |----------------------------------------------| used:86.74Mb 

Trả lời

10

Memory giao mã nguồn gốc bọc bởi JNI được phân bổ với quy trình JVM, nhưng không nằm dưới sự kiểm soát của mã Java của bạn. Nó không phải là một phần của heap, và không thể điều chỉnh thông qua các tham số JVM. Về cơ bản, bất cứ điều gì được phân bổ với một malloc gốc phải được quản lý bởi mã nguồn gốc đó. Nếu bạn đang kiểm soát các thư viện bạn đang sử dụng, bắt buộc của nó mà bạn đi qua nó và kiểm tra rò rỉ tài nguyên. Điều này đặc biệt quan trọng nếu điều này đang được sử dụng trong một quá trình lâu dài.

Theo kinh nghiệm của tôi, cách tiếp cận tốt nhất là kiểm tra việc sử dụng bộ nhớ thực tế của bạn bằng cách kéo số liệu thống kê JMX được JVM tiếp xúc. Một khi bạn có ý tưởng về dung lượng bộ nhớ mà ứng dụng Java của bạn tiêu thụ Bạn sẽ có một ý tưởng tốt hơn về nơi thiết lập cài đặt heap tối đa của bạn. Permgen không gian được sử dụng cho các định nghĩa lớp và như vậy, vì vậy bạn thực sự không cần nhiều bộ nhớ ở đó trừ khi bạn đang làm một bó tải lớp động.

Trong khi bạn không thể điều chỉnh bộ nhớ có sẵn cho thư viện JNI, hãy điều chỉnh bộ nhớ dành riêng cho vùng lưu trữ của bạn và các tài nguyên này có khả năng miễn phí để thư viện sử dụng.

Như dự kiến, hãy thêm các đỉnh bộ nhớ heap cùng nhau, nó xuất hiện khoảng 1022,19 (kích thước tối đa của heap). Khi heap cạn kiệt một GC chạy đầy đủ được khởi động và đống bẩn được khai hoang. Dựa trên những con số mà bạn đã cung cấp, tôi khuyên bạn nên bắt đầu với một Xmx512m. Điều này sẽ cung cấp cho phòng mã JNI của bạn để hơi thở.

Nếu bạn thấy rằng JVM đang bị đổ vỡ do thu gom rác quá mức, có nghĩa là bạn sắp hết Java đống quá nhanh, bạn có thể tăng phân bổ đó. Tuy nhiên, nếu nó ăn tối đa 512mb đủ nhanh để gây ra một tác động hiệu suất đáng chú ý, thì không chắc rằng bất cứ điều gì thiếu một sự gia tăng đáng kể sẽ có tác dụng lớn. Tất cả điều này phụ thuộc rất nhiều vào chương trình của bạn, nhanh như thế nào nó ăn vùng heap Java, và hiệu quả của việc chạy GC đầy đủ.

+1

Trong trường hợp tôi chưa nêu rõ điều này. Bạn thực sự không có cách nào để đặt giới hạn tối đa về dung lượng bộ nhớ mà thư viện JNI của bạn có thể yêu cầu. – allingeek

+0

Vì vậy, bạn đang nói để giảm thiểu bộ nhớ tổng thể được phân bổ cho quá trình JVM? Tôi có nên trừ tổng giá trị bộ nhớ được đưa ra bởi JMX từ giá trị được tiêu thụ bởi/phân bổ cho quá trình JVM để xác định số tiền được sử dụng bởi DLL không? – JoshDM

+1

Có, khoảng. Quá trình heap (có chứa vùng heap Java cộng với mọi thứ khác) bị giới hạn ở mức khoảng 2GB trên kiến ​​trúc 32 bit. Giới hạn là lớn hơn nhiều trên một vòm 64 bit. Nếu bạn đang phân bổ biểu diễn bộ nhớ cụ thể cho vùng heap Java và các thành phần Java cụ thể khác của bộ nhớ chương trình của bạn, điều đó không để lại nhiều chỗ cho việc phân bổ bộ nhớ JNI (được cấp phát dựa vào quy trình heap). – allingeek

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