直接内存
直接内存是Java程序的非常重要的组成部分,特别是NIO被广泛使用后,直接内存的使用也变得非常普遍。直接内存跳过了Java堆,使Java程序可以直接访问原生堆空间,因此一定程度的加快了内存空间的访问速度。这仅仅是读写上速度的优势,但是在内存分配时,就会存在劣势,下面我们将结合代码进行分析。
-XX:MaxDirectMemorySize设置最大直接可用内存
不设置则默认为最大堆空间(-Xmx指定)。当直接内存达到设定最大值时,就会触发GC,如果GC不能有效释放足够空间,就会引起OutOfMemeory错误。
读写速度的测试
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39
| public class AccessDirectBuffer { public void directAccess(){ ByteBuffer b = ByteBuffer.allocateDirect(500); long startTime = System.currentTimeMillis(); for(int i= 0;i<100000;i++){ for(int j = 0;j<100;j++) b.putInt(j); b.flip(); for(int j = 0;j<100;j++) b.getInt(j); } long endTime = System.currentTimeMillis(); b.clear(); System.out.println("DirectAccess consume:"+(endTime-startTime)); } public void bufferAccess(){ ByteBuffer b = ByteBuffer.allocate(500); long startTime = System.currentTimeMillis(); for(int i= 0;i<100000;i++){ for(int j = 0;j<100;j++) b.putInt(j); b.flip(); for(int j = 0;j<100;j++) b.getInt(j); } long endTime = System.currentTimeMillis(); b.clear(); System.out.println("DirectAccess consume:"+(endTime-startTime)); } public static void main(String[] args) { AccessDirectBuffer alloc = new AccessDirectBuffer(); alloc.bufferAccess(); alloc.directAccess(); alloc.bufferAccess(); alloc.directAccess(); } }
|
BufferAccess consume:276
DirectAccess consume:130
BufferAccess consume:199
DirectAccess consume:64
可以看出直接内存访问比对堆内存访问快很多
使用-server(稍后会讲,虚拟机的工作模式)后,结果
BufferAccess consume:270
DirectAccess consume:115
BufferAccess consume:234
DirectAccess consume:58
直接内存被Server优化后,速度提升更加明显
内存分配测试
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27
| public class AllocDirectBuffer { public void directAllocate(){ long startTime = System.currentTimeMillis(); for(int i= 0;i<100000;i++){ ByteBuffer b = ByteBuffer.allocateDirect(500); } long endTime = System.currentTimeMillis(); System.out.println("DirectAllocate consume:"+(endTime-startTime)); } public void bufferAllocate(){ long startTime = System.currentTimeMillis(); for(int i= 0;i<100000;i++){ ByteBuffer b = ByteBuffer.allocate(500); } long endTime = System.currentTimeMillis(); System.out.println("BufferAllocate consume:"+(endTime-startTime)); } public static void main(String[] args) { AllocDirectBuffer alloc = new AllocDirectBuffer(); alloc.bufferAllocate(); alloc.directAllocate(); alloc.bufferAllocate(); alloc.directAllocate(); } }
|
测试结果:
BufferAllocate consume:64
DirectAllocate consume:262
BufferAllocate consume:52
DirectAllocate consume:159
由此可见,在申请内存空间时,堆空间的速度远远高于直接内存
总结
直接内存适合请求分配内存次数,访问频繁的场合
如果内存空间需要频繁分配,则直接内存并不适合
虚拟机的两种工作模式
java虚拟机目前支持Client和Server两种运行模式,使用参数-Client和-Server指定。
使用java -version可以查看 当前模式
两者比较:
Server模式启动相对于Client模式来说较慢,因为Server模式会尝试手机更多的系统性能信息,使用更复杂的优化算法对程序进行优化。因此,当系统完全启动并进行运行稳定期后,Server模式的执行速度会远远快于Client模式。所以,对于后台长期运行的系统,使用-Server对性能提升帮助更大,对于用户界面程序,运行时间不长,又追求启动速度,Client更适合。