我通過創建一個字符串對象(new String(「some string」);)進行了1億次的java和jni之間的時間差異測試。當通過Java代碼測試時,執行時間大約需要1秒。但是當通過Jni代碼測試時,大約需要31秒。Java字符串創建對象:Java和JNI中的執行時間差異
對於JNI部分,我是否需要更改jni代碼設計或需要添加其他編譯器選項以提高執行速度?
環境:
MinGW的(32)
視窗8.1(64)
爪哇1.8(32)
C++編譯器的選項:-shared -m32 -Wl, - 添加-STDCALL別名
C++文件(下面給出在各文件中的代碼的所需部分):
class javaString {
jclass cls;
jmethodID method;
jstring strNew;
jobject obj;
public:
javaString() {
}
void myInit(JNIEnv *env) {
jclass cls1 = env-> FindClass("java/lang/String");
cls = (jclass) env->NewGlobalRef(cls1);
env->DeleteLocalRef(cls1);
method = env->GetMethodID(cls, "<init>", "(Ljava/lang/String;)V");
}
void myCall(JNIEnv *env, long lng) {
strNew = env->NewStringUTF("Apple");
for (long i = 0; i < lng; i++) {
obj = env->NewObject(cls, method, strNew);
env->DeleteLocalRef(obj);
}
env->DeleteLocalRef(strNew);
env->DeleteGlobalRef(cls);
}
};
javaString objStr;
JNIEXPORT void JNICALL Java_c_wrapperforjavaclass_clsNative_fnInit
(JNIEnv *env, jobject obj) {
objStr.myInit(env);
}
JNIEXPORT void JNICALL Java_c_wrapperforjavaclass_clsNative_fnCall
(JNIEnv *env, jobject obj, jint a) {
long lng = a;
objStr.myCall(env, lng);
}
Java文件:
public class clsNative {
public native void fnInit();
public native void fnCall(int a);
public void fnProcess2(int a){
for(int i=0;i<a;i++){
String str = new String("Apple");
str=null;
}
}
}
Java文件(測試):
clsNative a = new clsNative();
boolean blnJNITest=true;
String s1, s2;
s1 = Calendar.getInstance().getTime().toLocaleString();
int ii = 100000000; //100 million
if (blnJNITest) {
a.fnInit();
a.fnCall(ii);
} else {
a.fnProcess2(ii);
}
s2 = Calendar.getInstance().getTime().toLocaleString();
System.out.println(s1);
System.out.println(s2);
在字符串對象的地方(爪哇/郎/串),我有也試過以下
- StringBuilder strObj =新的StringBuilder(int capacity = 100);
- Integer intObj = New Integer(int value = 100);
在所有情況下,它大約需要同一時間。
你舉的例子清楚地表明,字節碼和本地代碼之間的轉換是一個相當昂貴的行動,所以我d建議僅將JNI用於不能在Java中本地執行的事情(如低級設備或操作系統交互),或者長時間的計算,其中發生的轉換損失超過執行例如,增加收益。 – fvu
你不會在你的Java代碼和JNI代碼中做同樣的事情。無論如何,當你使用'NewStringUTF' JNI API「創建」一個字符串(加上'DeleteLocalRef')時會發生什麼? – manuell
@manuell。謝謝。在fncall方法中處理DeleteLocalRef。 – Jeet