我将这两个方法的汇编代码打出来。可以看到HeapByteBuffer指令比DirectByteBuffer要多一些,所以速度也要慢一点。多在三点:
1.HeapByteBuffer多了一个offset字段,多了一次读内存和计算的操作。
2.HeapByteBuffer在写数组的时候要进行数组越界检查。
3.HeapByteBuffer数组对象地址是压缩指针,使用时需要解压。
0x0000000110342b40: mov %eax,-0x14000(%rsp)
0x0000000110342b47: push %rbp
0x0000000110342b48: sub $0x30,%rsp ;*synchronization entry
; - java.nio.DirectByteBuffer::put@-1 (line 297)
0x0000000110342b4c: mov %rsi,%rcx
0x0000000110342b4f: mov 0x1c(%rsi),%r11d ;*getfield limit
; - java.nio.Buffer::nextPutIndex@5 (line 520)
; - java.nio.DirectByteBuffer::put@5 (line 297)
0x0000000110342b53: mov 0x18(%rsi),%r8d ;*getfield position
; - java.nio.Buffer::nextPutIndex@1 (line 520)
; - java.nio.DirectByteBuffer::put@5 (line 297)
0x0000000110342b57: cmp %r11d,%r8d
0x0000000110342b5a: jge 0x0000000110342b80 ;*if_icmplt
; - java.nio.Buffer::nextPutIndex@8 (line 520)
; - java.nio.DirectByteBuffer::put@5 (line 297)
0x0000000110342b5c: mov 0x10(%rsi),%r10 //address字段
0x0000000110342b60: mov %r8d,%r9d
0x0000000110342b63: inc %r9d
0x0000000110342b66: mov %r9d,0x18(%rsi) ;*putfield position
; - java.nio.Buffer::nextPutIndex@27 (line 522)
; - java.nio.DirectByteBuffer::put@5 (line 297)
0x0000000110342b6a: movslq %r8d,%r11
0x0000000110342b6d: mov %dl,(%r10,%r11,1) ;*synchronization entry //写数据,dl为参数
; - java.nio.DirectByteBuffer::put@-1 (line 297)
0x0000000110342b71: mov %rsi,%rax
0x0000000110342b74: add $0x30,%rsp
0x0000000110342b78: pop %rbp
0x0000000110342b79: test %eax,-0xcd64b7f(%rip) # 0x00000001035de000
; {poll_return}
0x0000000110342b7f: retq
0x000000010e6e38c0: mov %eax,-0x14000(%rsp)
0x000000010e6e38c7: push %rbp
0x000000010e6e38c8: sub $0x30,%rsp ;*synchronization entry
; - java.nio.HeapByteBuffer::put@-1 (line 169)
0x000000010e6e38cc: mov %rsi,%r9
0x000000010e6e38cf: mov 0x2c(%rsi),%r10d ;*getfield hb
; - java.nio.HeapByteBuffer::put@1 (line 169)
0x000000010e6e38d3: mov 0x18(%rsi),%r11d ;*getfield position
; - java.nio.Buffer::nextPutIndex@1 (line 520)
; - java.nio.HeapByteBuffer::put@6 (line 169)
0x000000010e6e38d7: mov 0x1c(%rsi),%r8d ;*getfield limit
; - java.nio.Buffer::nextPutIndex@5 (line 520)
; - java.nio.HeapByteBuffer::put@6 (line 169)
0x000000010e6e38db: cmp %r8d,%r11d
0x000000010e6e38de: jge 0x000000010e6e3931 ;*if_icmplt
; - java.nio.Buffer::nextPutIndex@8 (line 520)
; - java.nio.HeapByteBuffer::put@6 (line 169)
0x000000010e6e38e0: mov %r11d,%ebp
0x000000010e6e38e3: add 0x24(%rsi),%ebp ;*iadd //offset字段
; - java.nio.HeapByteBuffer::ix@5 (line 131)
; - java.nio.HeapByteBuffer::put@9 (line 169)
0x000000010e6e38e6: inc %r11d
0x000000010e6e38e9: mov %r11d,0x18(%rsi) ;*putfield position
; - java.nio.Buffer::nextPutIndex@27 (line 522)
; - java.nio.HeapByteBuffer::put@6 (line 169)
0x000000010e6e38ed: mov 0xc(%r12,%r10,8),%r11d ; implicit exception: dispatches to 0x000000010e6e395d
0x000000010e6e38f2: cmp %r11d,%ebp //数组越界检查,r10是压缩指针
0x000000010e6e38f5: jae 0x000000010e6e3912
0x000000010e6e38f7: movslq %ebp,%r11
0x000000010e6e38fa: shl $0x3,%r10
0x000000010e6e38fe: mov %dl,0x10(%r10,%r11,1) ;*synchronization entry //数组中写入数据
; - java.nio.HeapByteBuffer::put@-1 (line 169)
0x000000010e6e3903: mov %rsi,%rax
0x000000010e6e3906: add $0x30,%rsp
0x000000010e6e390a: pop %rbp
0x000000010e6e390b: test %eax,-0xc1c6911(%rip) # 0x000000010251d000
; {poll_return}
0x000000010e6e3911: retq