[英]Fast way to pass data from C to Java via JNI
我在c中使用了一些快速通信庫,但我的應用程序的其余部分是用Java編寫的。 所以我想將收到的數據傳遞給我的java應用程序。
作為測試,我每隔5ms收到1000次消息。 這導致發件人應用程序完成發送時。 接收器應用程序仍需要時間來處理數據。
如果我刪除該行
(*g_env)->CallVoidMethod(g_env, store_callback, methodHandleMessage, top,
ts, fo, msg);
接收方應用程序在發送方發送完最后一條消息后立即完成。
有沒有機會加快速度?
void onMessageReceived(char* topic, char* timestamp, char* format,
char* message) {
JNIEnv * g_env;
int getEnvStat = (*g_vm)->GetEnv(g_vm, (void **) &g_env,
JNI_VERSION_1_8);
if (getEnvStat == JNI_EDETACHED) {
if ((*g_vm)->AttachCurrentThread(g_vm, (void **) &g_env, NULL) != 0) {
puts("Failed to attach");
fflush(stdout);
}
}
if (methodHandleMessage) {
} else {
jclass clazz = (*g_env)->GetObjectClass(g_env, store_callback);
methodHandleMessage =
(*g_env)->GetMethodID(g_env, clazz, "handleMessage",
"(Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;Ljava/lang/String;)V");
}
jstring top = (*g_env)->NewStringUTF(g_env, topic);
jstring ts = (*g_env)->NewStringUTF(g_env, timestamp);
jstring fo = (*g_env)->NewStringUTF(g_env, format);
jstring msg = (*g_env)->NewStringUTF(g_env, message);
//This line takes too long!
(*g_env)->CallVoidMethod(g_env, store_callback, methodHandleMessage, top,
ts, fo, msg);
}
您可以通過將類標記為final
來節省handleMessage
調用的一些時間,這將消除執行虛擬查找的需要。
如果這還不夠,並且如果不需要異步調用handleMessage
則可以避免直接調用它,而是將參數存儲在您將創建和管理的本地C數組中。 然后,您可以通過使用MonitorEnter
鎖定它,調用GetMethodID(g_env, clazz, "notify", "()V")
,然后使用MonitorExit
解鎖來通知Java對象可用的數據。
然后在Java方面, store_callback
實例將有一個專門的線程,只等待通知,如下所示:
while (true) {
synchronized (self) {
wait();
// we were informed that we received new data: now pull it out and process
String[][] args = getBufferedArgumentsViaJNI();
for (String[] arg : args) {
handleMessage(arg[0], arg[1], arg[2], arg[3]);
}
}
}
回到原生的一面,你需要實現getBufferedArgumentsViaJNI
來返回並清除所有緩沖參數的JNI數組(作為練習留給讀者)。
作為一個精明的讀者,您可能想知道為什么這會更快,因為您仍然需要在onMessageReceived
調用JNI方法以及執行JNI同步,因此它仍然會產生JNI開銷。 答案是雖然我不能保證消息處理總體上更快,但是“wait”調用可能會明顯加快,因為wait()
作為我見過的每個JVM上的本機方法實現。
java方法可能為空,但每次仍然調用GetEnv(),並創建4個復制到Java的字符串。 這些字符串有多大? 我試着用一些10-20個字符的字符串調用這個方法並測量它。 另一個簡單的解決方案(如果方法調用非常慢)用數組而不是字符串調用它,甚至可能將幾個字符串打包到一個數組中。 或者你也可以使用共享緩沖區( http://docs.oracle.com/javase/1.5.0/docs/guide/jni/spec/functions.html#GetDirectBufferAddress )
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.