首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > 编程 >

JVM内存储器模型以及垃圾回收

2012-11-03 
JVM内存模型以及垃圾回收http://www.rsky.com.cn/Article/java/201006/11926.htmlhttp://www.360doc.com/c

JVM内存模型以及垃圾回收
http://www.rsky.com.cn/Article/java/201006/11926.html
http://www.360doc.com/content/10/0811/19/61497_45329642.shtml
http://blog.csdn.net/user4570/archive/2009/04/01/4040687.aspx
在linux /unix 下或编辑 httpd.sh, 如下内容:

args='-J-server -Xms200m -Xmx1024m -Xloggc:./log/gc.log -XX:MaxNewSize=256m -XX:MaxPermSize=256m -Djava.awt.headless=true'

说明:
(1)J-server -Xms200m -Xmx1024m 其中,-Xms200m 表示启动时,初时内存大小,-Xmx1024m
最大内存占用大小。
(2)-XX:MaxNewSize=256m -XX:MaxPermSize=256m 表示:内存的永久保存区域的大小
(3)-Djava.awt.headless=true 解决在linux/unix验证码图片不能显示的问题。


而到了resin3.1, 则只需修改resin.conf,如下配置即可
<jvm-arg>-Xmx2048m</jvm-arg>
<jvm-arg>-Xms1024m</jvm-arg>
<jvm-arg>-Xss1m</jvm-arg>
<jvm-arg>-Xdebug</jvm-arg>
<jvm-arg>-Dcom.sun.management.jmxremote</jvm-arg>


/opt/resin-fuxi/bin/httpd.sh 增加 FUXI_XOA参数
FUXI_XOA="-Dxoa.hosts.fuxi.xoa.renren.com=10.3.19.200:8388"
args="-Xms4000M -Xmx4000M -J-server -J-Xss128k -J-XX:ThreadStackSize=128 -XX:MaxPermSize=128M -J-verbosegc -J-XX:+PrintGCDet
ails -J-XX:+UseParallelGC -J-XX:+PrintGCTimeStamps $FUXI_XOA  -Djava.library.path=/opt/resin-fuxi/libexec:/opt/j2sdk/lib:/us
r/lib64 -Djmagick.systemclassloader=false"


--------------------------------------------
在近日的测试中发现,无论resin.conf中配置的并发连接数多高,例如2048,resin实例能支持的并发活动线程数,或者说是活动连接数,最高只能去到500多。
linux下使用以下命令查看:ps -eLf |grep |wc -l


// default timeout
private long _timeout = 65000L;

private int _connectionMax = 512;//查找resin所有源码后,发现没有对这个值进行设置
private int _minSpareConnection = 16;

private int _keepaliveMax = -1;

private int _minSpareListen = 5;
private int _maxSpareListen = 10;

这个加大以后能到3000
<thread-pool>
    <!-- Maximum number of threads. -->
    <thread-max>20480</thread-max>

    <!-- Minimum number of spare connection threads. -->
    <spare-thread-min>10</spare-thread-min>
  </thread-pool>
然后就会报这个错误
  java.lang.OutOfMemoryError: unable to create new native thread
        at java.lang.Thread.start0(Native Method)
        at java.lang.Thread.start(Thread.java:574)
        at com.caucho.util.ThreadPool$ThreadLauncher.startConnection(ThreadPool.java:621)
        at com.caucho.util.ThreadPool$ThreadLauncher.run(ThreadPool.java:660)


这个限制可以换64位系统解决:
这个异常问题本质原因是我们创建了太多的线程,而能创建的线程数是有限制的,导致了异常的发生。能创建的线程数的具体计算公式如下:
(MaxProcessMemory - JVMMemory - ReservedOsMemory) / (ThreadStackSize) = Number of threads
MaxProcessMemory 指的是一个进程的最大内存
JVMMemory         JVM内存
ReservedOsMemory  保留的操作系统内存
ThreadStackSize      线程栈的大小
在java语言里, 当你创建一个线程的时候,虚拟机会在JVM内存创建一个Thread对象同时创建一个操作系统线程,而这个系统线程的内存用的不是JVMMemory,而是系统中剩下的内存(MaxProcessMemory - JVMMemory - ReservedOsMemory)。
结合上面例子我们来对公式说明一下:
MaxProcessMemory 在32位的 windows下是 2G
JVMMemory   eclipse默认启动的程序内存是64M
ReservedOsMemory  一般是150M左右
ThreadStackSize 32位 JDK 1.5默认的stacksize 256K左右
公式如下:
(2*1024*1024-64*1024-150*1024)/256 = 7336
公式计算所得7336,和实践7117基本一致(有偏差是因为ReservedOsMemory不能很精确)
由公式得出结论:你给JVM内存越多,那么你能创建的线程越少,越容易发生java.lang.OutOfMemoryError: unable to create new native thread。
咦,有点背我们的常理,恩,让我们来验证一下,依旧使用上面的测试程序,加上下面的JVM参数,测试结果如下:
ThreadStackSize      JVMMemory                    能创建的线程数
默认的256K             -Xms64m -Xmx64m    i = 7117
默认的256K             -Xms32m -Xmx32m    i = 7244
-Xss128k             -Xms64m -Xmx64m    i = ?
完全和公式一致。
三、解决问题:
1, 如果程序中有bug,导致创建大量不需要的线程或者线程没有及时回收,那么必须解决这个bug,修改参数是不能解决问题的。
2, 如果程序确实需要大量的线程,现有的设置不能达到要求,那么可以通过修改MaxProcessMemory,JVMMemory,ThreadStackSize这三个因素,来增加能创建的线程数:
a, MaxProcessMemory 使用64位操作系统
b, JVMMemory   减少JVMMemory的分配
c, ThreadStackSize  减小单个线程的栈大小

热点排行