如何确定直接内存的大小

        一般情况下,当我们明确需要使用直接内存的话,我们就会自己批定最大内存的大小,可以通过   -XX:MaxDirectMemorySize  参数来进行指定。当然通过Unsafe类来操作直接内存时,那么它是不会受这个参数的限制。比如ByteBuffer是受这个参数的限制。

        那么问题是,如果我们不通过 -XX:MaxDirectMemorySize 参数来指定最大直接内存的情况下,默认的直接内存是多大呢?接下来就通过一些案例测试一下。

案例

       这里准备一个简单的案例,如下图

      如何确定直接内存的大小

   (1)手动指定直接内存的大小

      指定直接内存大小。参数为 -XX:MaxDirectMemorySize=100m

      如何确定直接内存的大小

      运行代码后,结果如下

   如何确定直接内存的大小

    指定直接内存大小。参数为 -XX:MaxDirectMemorySize=128m

        如何确定直接内存的大小

     运行代码后,结果如下

如何确定直接内存的大小

 (2)不手动指定直接内存的大小,但指定堆的大小

         如何确定直接内存的大小

      运行代码后,结果如下

      如何确定直接内存的大小

      明明最大内存和代码里要求的是一样的大小,都是128M,为什么还是分配不下呢?

      再改动堆的大小,如图

       如何确定直接内存的大小

     运行代码,结果如下

如何确定直接内存的大小

     明明最大内存已经大于128M,为什么还是分配不下呢?

     再改动堆的大小,如图

     如何确定直接内存的大小

    运行代码,结果如下

    如何确定直接内存的大小

      看到这里,是不是很奇怪,为什么把最大的堆内存再调大一点,就可以分配下128M的直接内存呢?

总结

      通过这个案例分析, 我们得出以下结论:
      在没有显示的设置-XX:MaxDirectMemorySize 参数,通过 ByteBuffer 能够分配的直接内存空间大小就是堆的最大的可使用的大小。堆的最大的可使用的大小= 堆的最大值- 一个 Survivor 的大小(浪费的空间)
      所以就不难理解,把堆的最大值调整为135M时,为什么会 OOM,因为堆的最大的可使用的大小=135-10m=125m ,不能分配 128M 的对象;而调整为138M时,堆的最大的可使用的大小=138-10m=128m ,刚好可以分配 128M 的对象