Ví dụ thiếu bộ nhớ riêng
Để giúp bạn thấy việc cạn kiệt bộ nhớ riêng ảnh hưởng đến việc triển khai thực hiện Java mà bạn đang sử dụng như thế nào, mã mẫu của bài viết này (xem Tải về) có chứa một số chương trình Java gây ra sự cạn kiệt vùng heap riêng theo nhiều cách khác nhau. Các ví dụ này sử dụng một thư viện riêng được viết bằng C để tiêu dùng tất cả các vùng địa chỉ riêng và sau đó cố gắng thực hiện một số hành động có sử dụng bộ nhớ riêng. Các ví dụ được cung cấp đã được xây dựng (built) sẵn, mặc dù các chỉ thị biên dịch chúng được cung cấp trong tệp README.html trong thư mục cao nhất của gói ví dụ mẫu.
Lớp com.ibm.jtc.demos.NativeMemoryGlutton cung cấp phương thức gobbleMemory(), gọi hàm malloc trong một vòng lặp cho đến khi hầu như tất cả bộ nhớ riêng được sử dụng hết. Khi nó đã hoàn thành nhiệm vụ của mình, nó in số byte được cấp phát thành lỗi tiêu chuẩn như sau:
Allocated 1953546736 bytes of native memory before running out
Kết quả đầu ra được thu giữ cho mỗi lần trình diễn (demo) với một thời gian chạy Java của Sun và một thời gian chạy Java của IBM đang chạy trên Windows 32-bit. Các tệp mã nhị phân được cung cấp đã được thử nghiệm trên:
- Linux x86
- Linux PPC 32
- Linux 390 31
- Windows x86
Phiên bản sau đây của thời gian chạy Java của Sun đã được sử dụng để thu kết quả đầu ra:
java version "1.5.0_11" Java(TM) 2 Runtime Environment, Standard Edition (build 1.5.0_11-b03) Java HotSpot(TM) Client VM (build 1.5.0_11-b03, mixed
-------10--------20--------30--------40--------50--------60--------70--------80--------9|
|-------- XML error: The previous line is longer than the max of 90 characters ---------|
mode)
java version "1.5.0" Java(TM) 2 Runtime Environment, Standard Edition (build pwi32devifx-20071025 (SR 6b)) IBM J9 VM (build 2.3, J2RE 1.5.0 IBM J9 |-------10--------20--------30--------40--------50--------60--------70--------80--------9| |-------- XML error: The previous line is longer than the max of 90 characters ---------| 2.3 Windows XP x86-32 j9vmwi3223-2007100 7 (JIT enabled) J9VM -20071004_14218_lHdSMR JIT - 20070820_1846ifx1_r8 GC - 200708_10) JCL - 20071025 |-------10--------20--------30--------40--------50--------60--------70--------80--------9| |-------- XML error: The previous line is longer than the max of 90 characters ---------|
Cố gắng để khởi động một luồng khi hết bộ nhớ riêng
Lớp com.ibm.jtc.demos.StartingAThreadUnderNativeStarvation cố gắng để khởi động một luồng khi vùng địa chỉ tiến trình đã dùng hết. Đây là một cách phổ biến để phát hiện ra rằng tiến trình Java của bạn thiếu bộ nhớ vì nhiều ứng dụng bắt đầu các luồng trong vòng đời của chúng.
Kết quả đầu ra từ trình diễn (demo) StartingAThreadUnderNativeStarvation khi chạy trên thời gian chạy Java của IBM là:
Allocated 1019394912 bytes of native memory before running out JVMDUMP006I Processing Dump Event "systhrow", detail "java/lang/OutOfMemoryError" - |-------10--------20--------30--------40--------50--------60--------70--------80--------9| |-------- XML error: The previous line is longer than the max of 90 characters ---------| Please Wait. JVMDUMP007I JVM Requesting Snap Dump using 'C:\Snap0001.20080323.182114.5172.trc' JVMDUMP010I Snap Dump written to C:\Snap0001.20080323.182114.5172.trc JVMDUMP007I JVM Requesting Heap Dump using |-------10--------20--------30--------40--------50--------60--------70--------80--------9| |-------- XML error: The previous line is longer than the max of 90 characters ---------| 'C:\heapdump.20080323.182114.5172.phd' JVMDUMP010I Heap Dump written to C:\heapdump.20080323.182114.5172.phd JVMDUMP007I JVM Requesting Java Dump using |-------10--------20--------30--------40--------50--------60--------70--------80--------9| |-------- XML error: The previous line is longer than the max of 90 characters ---------| 'C:\javacore.20080323.182114.5172.txt' JVMDUMP010I Java Dump written to C:\javacore.20080323.182114.5172.txt JVMDUMP013I Processed Dump Event "systhrow", |-------10--------20--------30--------40--------50--------60--------70--------80--------9| |-------- XML error: The previous line is longer than the max of 90 characters ---------| detail "java/lang/OutOfMemoryError". java.lang.OutOfMemoryError: ZIP006:OutOfMemoryError, ENOMEM error in ZipFile.open at java.util.zip.ZipFile.open(Native Method) at java.util.zip.ZipFile.<init>(ZipFile.java:238) at java.util.jar.JarFile.<init>(JarFile.java:169) at java.util.jar.JarFile.<init>(JarFile.java:107) at com.ibm.oti.vm.AbstractClassLoader.fillCache(AbstractClassLoader.java:69) at |-------10--------20--------30--------40--------50--------60--------70--------80--------9| |-------- XML error: The previous line is longer than the max of 90 characters ---------| com.ibm.oti.vm.AbstractClassLoader.getResourceAsStream(AbstractClassLoader.java:113) |-------10--------20--------30--------40--------50--------60--------70--------80--------9| |-------- XML error: The previous line is longer than the max of 90 characters ---------| at java.util.ResourceBundle$1.run(ResourceBundle.java:1101) at java.security.AccessController.doPrivileged(AccessController.java:197) at java.util.ResourceBundle.loadBundle(ResourceBundle.java:1097) at java.util.ResourceBundle.findBundle(ResourceBundle.java:942) at java.util.ResourceBundle.getBundleImpl(ResourceBundle.java:779) at java.util.ResourceBundle.getBundle(ResourceBundle.java:716) at com.ibm.oti.vm.MsgHelp.setLocale(MsgHelp.java:103) at com.ibm.oti.util.Msg$1.run(Msg.java:44) at java.security.AccessController.doPrivileged(AccessController.java:197) at com.ibm.oti.util.Msg.<clinit>(Msg.java:41) at java.lang.J9VMInternals.initializeImpl(Native Method) at java.lang.J9VMInternals.initialize(J9VMInternals.java:194) at java.lang.ThreadGroup.uncaughtException(ThreadGroup.java:764) at java.lang.ThreadGroup.uncaughtException(ThreadGroup.java:758) at java.lang.Thread.uncaughtException(Thread.java:1315) K0319java.lang.OutOfMemoryError: Failed to fork OS thread at java.lang.Thread.startImpl(Native Method) at java.lang.Thread.start(Thread.java:979) |-------10--------20--------30--------40--------50--------60--------70--------80--------9| |-------- XML error: The previous line is longer than the max of 90 characters ---------| at com.ibm.jtc.demos.StartingAThreadUnderNativeStarvation.main( StartingAThreadUnderNativeStarvation.java:22)
Việc gọi java.lang.Thread.start() cố gắng để cấp phát bộ nhớ cho một luồng hệ điều hành mới. Nỗ lực này không thành công và đưa ra lỗi OutOfMemoryError . Các dòng JVMDUMP thông báo cho người dùng rằng thời gian chạy Java đã sinh ra dữ liệu gỡ lỗi OutOfMemoryError tiêu chuẩn của nó.
Việc cố gắng xử lý lỗi OutOfMemoryError đầu tiên gây ra một lỗi — thứ hai :OutOfMemoryError, ENOMEM error in ZipFile.open. Nhiều lỗi OutOfMemoryError là dấu hiệu phổ biến khi bộ nhớ tiến trình riêng đã cạn kiệt. Thông báo Failed to fork OS thread (bị thất bại khi phân nhánh luồng hệ điều hành) có lẽ là dấu hiệu thường hay gặp nhất của việc thiếu bộ nhớ riêng.
Các ví dụ được cung cấp với bài viết này bắt đầu một nhóm các lỗi OutOfMemoryError, nghiêm trọng hơn nhiều so với bất cứ những gì mà bạn có thể thấy với các ứng dụng riêng của bạn. Điều này một phần là vì hầu như tất cả các bộ nhớ riêng đã được sử dụng hết và không giống như trong một ứng dụng thực, bộ nhớ ấy không được giải phóng sau đó. Trong một ứng dụng thực, khi lỗi OutOfMemoryError được đưa ra, các luồng sẽ bị tắt và sức ép về bộ nhớ riêng có nhiều khả năng giảm bớt một chút, mang lại cho thời gian chạy một cơ hội để xử lý lỗi. Bản chất tầm thường của các bài thử nghiệm còn có nghĩa là toàn bộ các phần của thư viện lớp (như các hệ thống an ninh) vẫn chưa được khởi động — và việc khởi động chúng được điều khiển bởi thời gian chạy khi đang cố xử lý tình trạng thiếu bộ nhớ. Trong một ứng dụng thực, bạn có thể thấy một số lỗi được chỉ ra ở đây, nhưng ít khả năng bạn sẽ thấy tất cả các lỗi đồng thời.
Khi thực hiện cùng một bài thử nghiệm trên thời gian chạy Java của Sun, kết quả đầu ra trên cửa sổ màn hình như sau:
Allocated 1953546736 bytes of native memory before running out Exception in thread "main" java.lang.OutOfMemoryError: unable to create new native |-------10--------20--------30--------40--------50--------60--------70--------80--------9| |-------- XML error: The previous line is longer than the max of 90 characters ---------| thread at java.lang.Thread.start0(Native Method) at java.lang.Thread.start(Thread.java:574) at com.ibm.jtc.demos.StartingAThreadUnderNativeStarvation.main( StartingAThreadUnderNativeStarvation.java:22)
Mặc dù vết ngăn xếp và thông báo lỗi là hơi khác nhau, về bản chất các hành vi là giống nhau: việc cấp phát bộ nhớ riêng thất bại và một java.lang.OutOfMemoryError được đưa ra. Điều duy nhất để phân biệt các lỗi OutOfMemoryError được đưa ra trong kịch bản này với các lỗi được đưa ra do sử dụng hết vùng heap là thông báo.
Việc cố gắng để cấp phát một ByteBuffer trực tiếp khi thiếu bộ nhớ riêng
Lớp com.ibm.jtc.demos.DirectByteBufferUnderNativeStarvation cố gắng cấp phát một đối tượng java.nio.ByteBuffer trực tiếp (nghĩa là được hậu thuẫn riêng) khi vùng địa chỉ bị cạn kiệt. Khi chạy trong thời gian chạy Java của IBM, nó tạo kết quả đầu ra sau đây:
Allocated 1019481472 bytes of native memory before running out JVMDUMP006I Processing Dump Event "uncaught", detail "java/lang/OutOfMemoryError" - |-------10--------20--------30--------40--------50--------60--------70--------80--------9| |-------- XML error: The previous line is longer than the max of 90 characters ---------| Please Wait. JVMDUMP007I JVM Requesting Snap Dump using 'C:\Snap0001.20080324.100721.4232.trc' JVMDUMP010I Snap Dump written to C:\Snap0001.20080324.100721.4232.trc JVMDUMP007I JVM Requesting Heap Dump using |-------10--------20--------30--------40--------50--------60--------70--------80--------9| |-------- XML error: The previous line is longer than the max of 90 characters ---------| 'C:\heapdump.20080324.100721.4232.phd' JVMDUMP010I Heap Dump written to C:\heapdump.20080324.100721.4232.phd JVMDUMP007I JVM Requesting Java Dump using |-------10--------20--------30--------40--------50--------60--------70--------80--------9| |-------- XML error: The previous line is longer than the max of 90 characters ---------| 'C:\javacore.20080324.100721.4232.txt' JVMDUMP010I Java Dump written to C:\javacore.20080324.100721.4232.txt JVMDUMP013I Processed Dump Event "uncaught", |-------10--------20--------30--------40--------50--------60--------70--------80--------9| |-------- XML error: The previous line is longer than the max of 90 characters ---------| detail "java/lang/OutOfMemoryError". Exception in thread "main" java.lang.OutOfMemoryError: Unable to allocate 1048576 bytes of direct memory after |-------10--------20--------30--------40--------50--------60--------70--------80--------9| |-------- XML error: The previous line is longer than the max of 90 characters ---------| 5 retries at java.nio.DirectByteBuffer.<init>(DirectByteBuffer.java:167) at java.nio.ByteBuffer.allocateDirect(ByteBuffer.java:303) at com.ibm.jtc.demos.DirectByteBufferUnderNativeStarvation.main( DirectByteBufferUnderNativeStarvation.java:29) Caused by: java.lang.OutOfMemoryError |-------10--------20--------30--------40--------50--------60--------70--------80--------9| |-------- XML error: The previous line is longer than the max of 90 characters ---------| at sun.misc.Unsafe.allocateMemory(Native Method) at java.nio.DirectByteBuffer.<init>(DirectByteBuffer.java:154) ... 2 more
Trong kịch bản này, một lỗi OutOfMemoryError được đưa ra, khởi động một tài liệu lỗi mặc định. Lỗi OutOfMemoryError đạt tới đỉnh cao nhất của ngăn xếp của luồng chính và được in ra thành lỗi tiêu chuẩn stderr.
Khi chạy trong thời gian chạy Java của Sun, bài thử nghiệm này đưa ra kết quả đầu ra như sau:
Allocated 1953546760 bytes of native memory before running out Exception in thread "main" java.lang.OutOfMemoryError at sun.misc.Unsafe.allocateMemory(Native Method) at java.nio.DirectByteBuffer.<init>(DirectByteBuffer.java:99) at java.nio.ByteBuffer.allocateDirect(ByteBuffer.java:288) at com.ibm.jtc.demos.DirectByteBufferUnderNativeStarvation.main( DirectByteBufferUnderNativeStarvation.java:29)
Phần tiếp theo: Các cách tiếp cận và kỹ thuật gỡ rối