首页 > 代码库 > JVM的DirectMemory设置

JVM的DirectMemory设置

-server
 设置jvm使server模式,特点是启动速度比较慢,但运行时性能和内存管理效率很高,适用于生产环境。在具有64位能力的jdk环境下将默认启用该模式,而忽略-client参数。


几台服务器的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的DirectMemory设置