JVM的DirectMemory设置

原文:http://dongliu.net/post/504141

 

几台服务器的JVM占用内存总是持续增长,大大超过-Xmx设定的值,服务器物理内存几乎被耗尽。

使用jmap查看JVM的内存使用,发现jvm的堆大小完全在-Xmx参数设定的范围之内,那问题只能处在别的地方了。

JVM除了堆内存之外,就只有栈内存和DirectMemory了。栈空间每个线程是固定的,线程数也没可能多到可以占用这么多内存的程序,所以怀疑的目标就在DirectMemory上了。

DirectMemory是java nio引入的,直接以native的方式分配内存,不受jvm管理。这种方式是为了提高网络和文件IO的效率,避免多余的内存拷贝而出现的。DirectMemory占用的大小没有直接的工具或者API可以查看,不过这个在Bits类中是有两个字段存储了最大大小和已分配大小的,使用反射可以拿到这个数据:

 

Class <?>  c  =  Class . forName ( "java.nio.Bits" );
Field  maxMemory  =  c . getDeclaredField ( "maxMemory" );
maxMemory . setAccessible ( true );
Field  reservedMemory  =  c . getDeclaredField ( "reservedMemory" );
reservedMemory . setAccessible ( true );
Long  maxMemoryValue  =  ( Long ) maxMemory . get ( null );
Long  reservedMemoryValue  =  ( Long ) reservedMemory . get ( null );

 

结果证实了猜测,DirectMemory增长失控了。

原来,DirectMemory 的默认大小是64M,而JDK6之前和JDK6的某些版本的SUN JVM,存在一个BUG,在用-Xmx设定堆空间大小的时候,也设置了DirectMemory的大小。加入设置了-Xmx2048m,那么jvm最终可分配的内存大小为4G多一些,是预期的两倍。

 

解决方式是设置jvm参数-XX:MaxDirectMemorySize=128m,指定DirectMemory的大小。

你可能感兴趣的:(jvm)