Java 内存不足错误(本机内存),达到了进程大小限制(32 位 linux)
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/18630790/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Java Out of Memory Error(Native memory), the process size limit was hit(32-bit linux)
提问by lamplet
I am testing the performence of a web application, and have got "Out of Memory Error"(native memory).
我正在测试 Web 应用程序的性能,并且遇到了“内存不足错误”(本机内存)。
I have test several times, and every time it "failed to allocate 83886088 bytes for Chunk::new" and died.
我已经测试了几次,每次它“未能为 Chunk::new 分配 83886088 字节”而死。
I print the memory size every minute, and found that the VmSize was 2924700 kB before the process died.
我每分钟打印一次内存大小,发现进程终止前 VmSize 为 2924700 kB。
I think that the process size limit was hit. I change -Xmx2000m to -Xmx1900m and it's OK now.
我认为达到了进程大小限制。我将 -Xmx2000m 更改为 -Xmx1900m,现在可以了。
Some questions:
一些问题:
1.How to comfirm that the process size limit was hit. It's not exactly 3G memory.
1.如何确认已达到进程大小限制。它不完全是3G内存。
2.Why JVM allocate 83886088 bytes memory every time? From the exception stack, it seems that it's related to GC things.
2.为什么JVM每次分配83886088字节的内存?从异常栈上看,好像跟GC的东西有关。
3.How many memory should be reserved for JVM besides heap memory(-Xmx) and non-heap memory(-XX:MaxPermSize)? And how to know how many it's using now?
3.除了堆内存(-Xmx)和非堆内存(-XX:MaxPermSize),JVM还应该预留多少内存?以及如何知道它现在使用了多少?
Thanks and sorry for my poor English.
感谢并为我糟糕的英语感到抱歉。
Linux 2.6.16.60-0.83.2-bigsmp JRE 6.0_25-b06 Tomcat 7.0.37
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
回答by Peter Lawrey
print the memory size every minute, and found that the VmSize was 2924700 kB before the process died.
每分钟打印一次内存大小,发现进程死前VmSize为2924700 kB。
AFAIK On Linux the OS uses about 1 GB. You need virtual memory for thread stacks, shared libraries, Perm Gen, memory mapped files, and any native resources.
AFAIK 在 Linux 上,操作系统使用大约 1 GB。您需要用于线程堆栈、共享库、永久代、内存映射文件和任何本机资源的虚拟内存。
If you are getting anywhere near this limit (or if you just have a 64-bit processor) you really should be using a 64-bit OS and JVM. I would use Java 6 update 45, which is end of free support, if not Java 7 update 25.
如果您接近此限制(或者如果您只有 64 位处理器),您真的应该使用 64 位操作系统和 JVM。如果不是 Java 7 更新 25,我将使用 Java 6 更新 45,这是免费支持的结束。
回答by Aaron Digulla
process size limit
进程大小限制
Modern Linux OSs can use more than 4GB of RAM when in the 32bit version by using something called Physical Address Extension (PAE).
通过使用称为物理地址扩展 (PAE) 的东西,现代 Linux 操作系统在 32 位版本中可以使用超过 4GB 的 RAM 。
But if you don't do anything, 3GB seems like a reasonable limit that processes may hit.
但是,如果您什么都不做,3GB 似乎是进程可能达到的合理限制。
That said, this is completely unrelated to your case. The error is not from the kernel (you didn't get a core dump) but from the Java runtime.
也就是说,这与您的情况完全无关。错误不是来自内核(您没有得到核心转储)而是来自 Java 运行时。
The reason why it happens in the GC is that some other thread asked for another 83886088 bytes of free memory and there wasn't any left. So the VM started the GC to make room. Unfortunately, all objects were still in use -> out of memory error.
它发生在 GC 中的原因是其他一些线程要求另外 83886088 字节的空闲内存,但没有剩余。因此 VM 启动了 GC 以腾出空间。不幸的是,所有对象仍在使用中 -> 内存不足错误。
Why JVM allocate 83886088 bytes memory every time?
为什么JVM每次分配83886088字节的内存?
Software should be deterministic, that is it should produce the same results every time you run it.
软件应该是确定性的,即每次运行它都应该产生相同的结果。
Look at the other threads. One of them just tried to allocate exactly this memory.
看看其他线程。其中一个只是试图准确分配这个内存。
How many memory should be reserved for JVM besides heap memory(-Xmx) and non-heap memory(-XX:MaxPermSize)?
除了堆内存(-Xmx)和非堆内存(-XX:MaxPermSize),JVM还应该预留多少内存?
That depends on what your application does. But usually, out of memory means you have a memory leak (i.e. something holds on to big objects that it doesn't really need anymore).
这取决于您的应用程序做什么。但通常,内存不足意味着您有内存泄漏(即某些东西保留了它不再真正需要的大对象)。
Use a profiler like MATor YourKitto determine what that could be.
And how to know how many it's using now?
以及如何知道它现在使用了多少?
Use jconsoleor VisualVMto monitor the memory usage.
Related:
有关的:
回答by Pinaki Mukherjee
Try to change the stack size for a thread, use the -Xss=Nflag (e.g., -Xss=256k). By default for linux the size is 320 KB(In 64 bit machine the size is 1 MB). Generally, Out of Native Memory happens because of following reasons:
尝试更改线程的堆栈大小,使用-Xss=N标志(例如 - Xss=256k)。默认情况下,Linux 的大小为320 KB(在 64 位机器中,大小为 1 MB)。通常,Out of Native Memory 发生的原因如下:
Please note that changing the stack size will help in case of 1 and 2.
请注意,在 1 和 2 的情况下,更改堆栈大小将有所帮助。
- In a 32-bit JVM, the process is at its 4 GB (or less, depending on the OS) maximum size.
- The system has actually run out of virtual memory.
- On Unix-style systems, the user has already created (between all programs she is running) the maximum number of processes configured for her login. Individual threads are considered a process in that regard.
- 在 32 位 JVM 中,进程的最大大小为 4 GB(或更少,取决于操作系统)。
- 系统实际上已经用完了虚拟内存。
- 在 Unix 风格的系统上,用户已经创建了(在她运行的所有程序之间)为她的登录配置的最大进程数。在这方面,单个线程被视为一个进程。
Hope this helps.
希望这可以帮助。
Regards, Pinaki
问候, 皮纳基