JAVA虚拟机起步-虚拟机调优

JAVA虚拟机起步OutOfMemory问题解决记录。

   问题: JAVA虚拟机报错

    # java.lang.OutOfMemoryError: requested 32756 bytes for ChunkPool::allocate. Out of swap space?
    #
    #  Internal Error (allocation.cpp:117), pid=26666, tid=2409851824
    #  Error: ChunkPool::allocate

    解决办法:

    平衡每个线程需要的内存存储器的堆栈大小,在程序内部控制线程总数量。

 

   理论:

JVM线程堆栈

  1.  应用程序中的每个线程都需要内存来存储器堆栈(用于在调用函数时持有局部变量并维护状态的内存区域)。每个 Java 线程都需要堆栈空间来运行。

  2.  根据实现的不同,Java 线程可以分为本机线程和 Java 堆栈。除了堆栈空间,每个线程还需要为线程本地存储(thread-local storage)和内部数据结构提供一些本机内存。

 

JVM堆栈大小

  1. -Xss 128k:设置每个线程的堆栈大小。JDK5.0以后每个线程堆 栈大小为1M,以前每个线程堆栈大小为256K。更具应用的线程所需内存大小进行调整。

  2. 在相同物理内存下,减小这个值能生成更多的线程。但是操作系统对一 个进程内的线程数还是有限制的,不能无限生成,经验值在3000~5000左右。 

  3. JVM heap与JVM私有内存、JVM线程堆栈大小间的关系及平衡。

  4. 线程栈的大小是个双刃剑,如果设置过小,可能会出现栈溢出,特别是在该线程内有递归、大的循环时时出现溢出的可能性更大,如果该值设置过大,就有影响到创建栈的数量,如果是多线程的应用,就会出现内存溢出的错误.

    经验:

    JAVA开大量线程需要注意的地方有,一个是unlimit设置可以保证操作系统开启的文件数量,另一个就是需要考虑物理内存大小,最后要控制好线程总数量的上限。

   案例:

JAVA程序在实现大量Socket连接代理过程中,入口是通过异步SocketServer接口数据,开启的accept和reader可控,出口需要一个连接开启一个目标Socket(每个Socket对应一个线程)。

通常一台机器开启的线程数值为3000-5000个。个人感觉是跟物理内存有关,如果是4G的物理内存,每个线程默认开销1M空间,5000个线程会全部暂用物理内存,JAVA虚拟机在开启新线程是就会出现 java.lang.OutOfMemoryError: requested 32756 bytes for ChunkPool::allocate. Out of swap space?

 基于此案例,首先想到的是通过优化程序降低线程的数量,然后通过调整虚拟机参数降低线程占用内存数量。

 

附:

#
# A fatal error has been detected by the Java Runtime Environment:
#
# java.lang.OutOfMemoryError: requested 32756 bytes for ChunkPool::allocate. Out of swap space?
#
#  Internal Error (allocation.cpp:117), pid=26666, tid=2409851824
#  Error: ChunkPool::allocate
#
# JRE version: 6.0_17-b04
# Java VM: Java HotSpot(TM) Server VM (14.3-b01 mixed mode linux-x86 )
# If you would like to submit a bug report, please visit:
#   http://java.sun.com/webapps/bugreport/crash.jsp

 

在处理此问题过程中,有的文章说是需要更换jdk版本,有的说是32bit和64bit的问题。

个人来看,问题的关键是java虚拟机无法为新线程申请内存。写的程序没有控制好内存。

你可能感兴趣的:(JAVA虚拟机起步-虚拟机调优)