簡體   English   中英

Java Out of Memory Error(本機內存),進程大小限制被命中(32位linux)

[英]Java Out of Memory Error(Native memory), the process size limit was hit(32-bit linux)

我正在測試Web應用程序的性能,並且出現“Out of Memory Error”(本機內存)。

我已多次測試,每次“未能為Chunk :: new分配83886088字節”而死亡。

我每分鍾打印一次內存大小,發現VmSize在進程死亡之前是2924700 kB。

我認為流程大小限制受到了影響。 我將-Xmx2000m更改為-Xmx1900m,現在就可以了。

一些問題:

1.如何確認流程大小限制被打中。 這不完全是3G內存。

2.為什么JVM每次分配83886088字節的內存? 從異常堆棧看,它似乎與GC有關。

3.除了堆內存(-Xmx)和非堆內存(-XX:MaxPermSize)之外,應該為JVM保留多少內存? 如何知道它現在使用了多少?

謝謝,抱歉我的英語不好。

Linux 2.6.16.60-0.83.2-bigsmp JRE 6.0_25-b06 Tomcat 7.0.37

jvm options: -Xms2000m -Xmx2000m -XX:PermSize=256M -XX:MaxPermSize=512m -XX:+UseConcMarkSweepGC -XX:+UseParNewGC

/proc/meminfo:
MemTotal:     24935548 kB
MemFree:      13564968 kB

# Native memory allocation (malloc) failed to allocate 83886088 bytes for Chunk::new
# Possible reasons:
#   The system is out of physical RAM or swap space
#   In 32 bit mode, the process size limit was hit
...
# This output file may be truncated or incomplete.
#
#  Out of Memory Error (allocation.cpp:317), pid=18217, tid=275671968

---------------  T H R E A D  ---------------

Current thread (0x105a1c00):  VMThread [stack: 0x10666000,0x106e7000] [id=18243]

Stack: [0x10666000,0x106e7000],  sp=0x106e5ae0,  free space=510k
Native frames: (J=compiled Java code, j=interpreted, Vv=VM code, C=native code)
V  [libjvm.so+0x724710]  VMError::report_and_die()+0x2b0
V  [libjvm.so+0x2f68ef]  report_vm_out_of_memory(char const*, int, unsigned, char const*)+0x4f
V  [libjvm.so+0x1576fc]  Chunk::operator new(unsigned, unsigned)+0x5c
V  [libjvm.so+0x157c26]  Arena::grow(unsigned)+0x26
V  [libjvm.so+0x6457e9]  resource_allocate_bytes(unsigned)+0x49
V  [libjvm.so+0x3a03ef]  GenericGrowableArray::raw_allocate(int)+0xbf
V  [libjvm.so+0x3402ee]  GrowableArray<oopDesc*>::grow(int)+0x3e
V  [libjvm.so+0x3a62b1]  FindInstanceClosure::do_object(oopDesc*)+0x51
V  [libjvm.so+0x2ae571]  CompactibleFreeListSpace::object_iterate(ObjectClosure*)+0x51
V  [libjvm.so+0x38d066]  GenerationObjIterateClosure::do_space(Space*)+0x16
V  [libjvm.so+0x2d6498]  ConcurrentMarkSweepGeneration::space_iterate(SpaceClosure*, bool)+0x18
V  [libjvm.so+0x38be22]  Generation::object_iterate(ObjectClosure*)+0x22
V  [libjvm.so+0x2d9f9d]  ConcurrentMarkSweepGeneration::object_iterate(ObjectClosure*)+0x4d
V  [libjvm.so+0x37fd65]  GenCollectedHeap::object_iterate(ObjectClosure*)+0x55
V  [libjvm.so+0x3a61fe]  HeapInspection::find_instances_at_safepoint(klassOopDesc*, GrowableArray<oopDesc*>*)+0x3e
V  [libjvm.so+0x6eca91]  ConcurrentLocksDump::dump_at_safepoint()+0xf1
V  [libjvm.so+0x6e7561]  Threads::print_on(outputStream*, bool, bool, bool)+0x201
V  [libjvm.so+0x734927]  VM_PrintThreads::doit()+0x27
V  [libjvm.so+0x734576]  VM_Operation::evaluate()+0x46
V  [libjvm.so+0x733a23]  VMThread::evaluate_operation(VM_Operation*)+0x83
V  [libjvm.so+0x733c90]  VMThread::loop()+0x190
V  [libjvm.so+0x733780]  VMThread::run()+0x80
V  [libjvm.so+0x5e294e]  java_start(Thread*)+0x14e
C  [libpthread.so.0+0x54ab]  short+0x8b

VM_Operation (0x0caff000): PrintThreads, mode: safepoint, requested by thread 0x09ec3800


---------------  P R O C E S S  ---------------

Java Threads: ( => current thread )
...//209 Java Threads

Heap
 par new generation   total 147456K, used 126550K [0x161f0000, 0x201f0000, 0x201f0000)
  eden space 131072K,  92% used [0x161f0000, 0x1d869d18, 0x1e1f0000)
  from space 16384K,  31% used [0x1e1f0000, 0x1e70be78, 0x1f1f0000)
  to   space 16384K,   0% used [0x1f1f0000, 0x1f1f0000, 0x201f0000)
 concurrent mark-sweep generation total 1884160K, used 1697819K [0x201f0000, 0x931f0000, 0x931f0000)
 concurrent-mark-sweep perm gen total 262144K, used 61769K [0x931f0000, 0xa31f0000, 0xb31f0000)

Code Cache  [0xb391f000, 0xb44b7000, 0xb691f000)
 total_blobs=3924 nmethods=3719 adapters=157 free_code_cache=38272704 largest_free_block=9600

每分鍾打印一次內存大小,發現VmSize在進程死亡之前是2924700 kB。

AFAIK在Linux上,操作系統使用大約1 GB。 您需要虛擬內存用於線程堆棧,共享庫,Perm Gen,內存映射文件和任何本機資源。

如果你接近這個限制(或者如果你只有一個64位處理器),你真的應該使用64位操作系統和JVM。 我會使用Java 6更新45,這是免費支持的結束,如果不是Java 7更新25。

流程大小限制

通過使用稱為物理地址擴展(PAE)的東西,現代Linux操作系統在32位版本中可以使用超過4GB的RAM。

但如果你不做任何事情,3GB似乎是一個合理的限制,進程可能會受到影響。

那就是說,這與你的情況完全無關。 錯誤不是來自內核(您沒有獲得核心轉儲),而是來自Java運行時。

它在GC中發生的原因是一些其他線程要求另外83886088字節的空閑內存並且沒有任何剩余。 因此VM啟動了GC以騰出空間。 不幸的是,所有對象仍在使用 - >內存不足錯誤。

為什么JVM每次分配83886088字節的內存?

軟件應該是確定性的,即每次運行它時應該產生相同的結果。

看看其他線程。 其中一個人試圖准確分配這個記憶。

除了堆內存(-Xmx)和非堆內存(-XX:MaxPermSize)之外,應該為JVM保留多少內存?

這取決於您的應用程序的功能。 但通常情況下,內存不足意味着你有內存泄漏(即大型對象上存在的東西,它實際上並不需要它)。

使用MATYourKit等分析器來確定可能的內容。

如何知道它現在使用了多少?

使用jconsoleVisualVM監視內存使用情況。

有關:

嘗試更改線程的堆棧大小,使用-Xss = N標志(例如, - Xss = 256k )。 默認情況下,linux的大小為320 KB (在64位計算機中,大小為1 MB)。 通常,Out of Native Memory由於以下原因而發生:

請注意,更改堆棧大小將有助於1和2的情況。

  1. 在32位JVM中,該進程的最大大小為4 GB(或更低,取決於操作系統)。
  2. 系統實際上耗盡了虛擬內存。
  3. 在Unix風格的系統上,用戶已經(在她正在運行的所有程序之間)創建了為其登錄配置的最大進程數。 在這方面,單個線程被認為是一個過程。

希望這可以幫助。

此致,Pinaki

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM