我正在测试Web应用程序的性能,并且已经出现了内存错误"(本机内存)。
我已多次测试,每次都没有为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
答案 0 :(得分:3)
每分钟打印一次内存大小,发现VmSize在进程死亡前为2924700 kB。
AFAIK在Linux上,操作系统使用大约1 GB。您需要虚拟内存用于线程堆栈,共享库,Perm Gen,内存映射文件以及任何本机资源。
如果你接近这个限制(或者如果你只有一个64位处理器),你真的应该使用64位操作系统和JVM。我会使用Java 6 update 45,这是免费支持的结束,如果不是Java 7更新25。
答案 1 :(得分:1)
流程大小限制
使用名为Physical Address Extension (PAE)的东西,现代Linux操作系统在32位版本中可以使用超过4GB的RAM。
但是如果你什么都不做,那么3GB似乎是一个合理的限制,进程可能会受到影响。
那就是说,这与你的情况完全无关。错误不是来自内核(您没有获得核心转储),而是来自Java运行时。
它在GC中发生的原因是其他一些线程要求另外83886088字节的空闲内存并且没有任何剩余。因此VM启动了GC以腾出空间。不幸的是,所有对象仍在使用中 - &gt;内存不足错误。
为什么JVM每次都会分配83886088字节的内存?
软件应该是确定性的,即每次运行时都应该产生相同的结果。
看看其他主题。其中一个只是试图准确分配这个记忆。
除了堆内存(-Xmx)和非堆内存(-XX:MaxPermSize)之外,应该为JVM保留多少内存?
这取决于您的应用程序的功能。但通常情况下,内存不足意味着你有一个内存泄漏(即某些东西不再存在于大型对象上)。
如何知道它现在使用了多少?
相关:
答案 2 :(得分:0)
尝试更改线程的堆栈大小,使用 -Xss = N 标志(例如, - Xss = 256k )。默认情况下,linux的大小为 320 KB (在64位计算机中,大小为1 MB)。通常,Out of Native Memory由于以下原因而发生:
请注意,在1和2的情况下更改堆栈大小会有所帮助。
希望这有帮助。
此致 皮纳基环礁