У меня есть простая функция JNI, которую я использую для чтения данных из файла в byte[]
из кода C UnixUtil.unsafeReadToByteArray
, который реализован как:
JNIEXPORT jlong JNICALL Java_net_xxxxxxx_UnixUtil_unsafeReadToByteArray
(JNIEnv *e, jclass jc, jint fd, jbyteArray array, jlong offset, jlong count){
signed char *array_native_ptr = (*e) -> GetByteArrayElements(e, array, NULL);
ssize_t bytes_read = read(fd, array_native_ptr + offset, (size_t) count);
(*e) -> ReleaseByteArrayElements(e, array, array_native_ptr, 0);
return bytes_read;
}
Профилирование Java-приложения, выполняющего функцию, обнаружилоськакой-то неясный результат.Вот вершина:
Одной из самых горячих вещей оказалась некая инструкция по адресу 0x18eb1f
от libc-2.27.so
.Я хотел понять, что это было, но GDB не знает об этом
(gdb) disas 0x18eb1f
No function contains specified address
Objdump'ing libc для grep адреса, я обнаружил, что
18eb0b: 72 0f jb 18eb1c <__nss_group_lookup@GLIBC_2.2.5+0x24ddc>
[...]
18eb1c: 48 89 d1 mov %rdx,%rcx
18eb1f: f3 a4 rep movsb %ds:(%rsi),%es:(%rdi)
Что выглядит как часть__nss_group_lookup
, в то время как __nss_group_lookup
, кажется, не содержит адрес:
(gdb) disas __nss_group_lookup
Dump of assembler code for function __nss_passwd_lookup:
0x0000000000169d40 <+0>: mov rax,QWORD PTR [rip+0x281121] # 0x3eae68
0x0000000000169d47 <+7>: mov DWORD PTR fs:[rax],0x26
0x0000000000169d4e <+14>: mov eax,0xffffffff
0x0000000000169d53 <+19>: ret
End of assembler dump. making the things more unclear then it was before.
, что делает вещи более неясными, чем раньше.
Вопрос: Можете ли вы дать какой-нибудь намек, где искать, чтобы понять, почему инструкция, принадлежащая __nss_group_lookup
, самая горячая при вызове jni_GetByteArrayElements
/ jni_ReleaseByteArrayElements
и что это на самом деле.
Я ожидалпоскольку jni_GetByteArrayElements
/ jni_ReleaseByteArrayElements
копирует byte[]
из кучи Java в кучу C через memcpy
, это будет самый горячий вариант.