JVM的DirectMemory設置

-server
 設置jvm使server模式,特色是啓動速度比較慢,但運行時性能和內存管理效率很高,適用於生產環境。在具備64位能力的jdk環境下將默認啓用該模式,而忽略-client參數。java


幾臺服務器的JVM佔用內存老是持續增加,大大超過-Xmx設定的值,服務器物理內存幾乎被耗盡。服務器

使用jmap查看JVM的內存使用,發現jvm的堆大小徹底在-Xmx參數設定的範圍以內,那問題只能處在別的地方了。網絡

JVM除了堆內存以外,就只有棧內存和DirectMemory了。棧空間每一個線程是固定的,線程數也沒可能多到能夠佔用這麼多內存的程序,因此懷疑的目標就在DirectMemory上了。jvm

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增加失控了。spa

原來,DirectMemory 的默認大小是64M,而JDK6以前和JDK6的某些版本的SUN JVM,存在一個BUG,在用-Xmx設定堆空間大小的時候,也設置了DirectMemory的大小。加入設置了-Xmx2048m,那麼jvm最終可 分配的內存大小爲4G多一些,是預期的兩倍。線程

解決方式是設置jvm參數-XX:MaxDirectMemorySize=128m,指定DirectMemory的大小。orm

相關文章
相關標籤/搜索