Fixed crash with jni localreference table overflow after updating large number of outdated maps.

This commit is contained in:
Dmitry Yunitsky 2015-06-24 12:08:35 +03:00 committed by Alex Zolotarev
parent 23e5564bf3
commit d2748b12c7
3 changed files with 44 additions and 14 deletions

View file

@ -81,6 +81,9 @@ namespace jni
jmethodID mid = env->GetMethodID(cls, fn, sig);
ASSERT(mid, ("Can't get methodID", fn, sig, DescribeException()));
env->DeleteLocalRef(cls);
return mid;
}
@ -219,4 +222,18 @@ namespace jni
static_cast<jint>(point.x),
static_cast<jint>(point.y));
}
// TODO
// make ScopedLocalRef wrapper similar to https://android.googlesource.com/platform/libnativehelper/+/jb-mr1.1-dev-plus-aosp/include/nativehelper/ScopedLocalRef.h
// for localrefs automatically removed after going out of scope
// This util method dumps content of local and global reference jni tables to logcat for debug and testing purposes
void DumpDalvikReferenceTables()
{
JNIEnv * env = jni::GetEnv();
jclass vm_class = env->FindClass("dalvik/system/VMDebug");
jmethodID dump_mid = env->GetStaticMethodID(vm_class, "dumpReferenceTables", "()V");
env->CallStaticVoidMethod(vm_class, dump_mid);
env->DeleteLocalRef(vm_class);
}
} // namespace jni

View file

@ -47,4 +47,6 @@ namespace jni
jobject GetNewPoint(JNIEnv * env, m2::PointD const & point);
jobject GetNewPoint(JNIEnv * env, m2::PointI const & point);
void DumpDalvikReferenceTables();
}

View file

@ -24,8 +24,8 @@ public:
jclass klass = env->FindClass("com/mapswithme/maps/downloader/DownloadChunkTask");
ASSERT ( klass, () );
jmethodID methodId = env->GetMethodID(klass, "<init>", "(JLjava/lang/String;JJJ[BLjava/lang/String;)V");
ASSERT ( methodId, () );
static jmethodID initMethodId = env->GetMethodID(klass, "<init>", "(JLjava/lang/String;JJJ[BLjava/lang/String;)V");
ASSERT ( initMethodId, () );
// User id is always the same, so do not waste time on every chunk call
static string uniqueUserId = GetPlatform().UniqueClientId();
@ -37,21 +37,32 @@ public:
postBody = env->NewByteArray(postBodySize);
env->SetByteArrayRegion(postBody, 0, postBodySize, reinterpret_cast<jbyte const *>(pb.c_str()));
}
m_self = env->NewGlobalRef(env->NewObject(klass,
methodId,
reinterpret_cast<jlong>(&cb),
env->NewStringUTF(url.c_str()),
static_cast<jlong>(beg),
static_cast<jlong>(end),
static_cast<jlong>(expectedFileSize),
postBody,
env->NewStringUTF(uniqueUserId.c_str())));
jstring jUrl = env->NewStringUTF(url.c_str());
jstring jUserId = env->NewStringUTF(uniqueUserId.c_str());
jobject const localSelf = env->NewObject(klass,
initMethodId,
reinterpret_cast<jlong>(&cb),
jUrl,
static_cast<jlong>(beg),
static_cast<jlong>(end),
static_cast<jlong>(expectedFileSize),
postBody,
jUserId);
m_self = env->NewGlobalRef(localSelf);
ASSERT ( m_self, () );
methodId = env->GetMethodID(klass, "start", "()V");
ASSERT ( methodId, () );
env->DeleteLocalRef(localSelf);
env->DeleteLocalRef(postBody);
env->DeleteLocalRef(jUrl);
env->DeleteLocalRef(jUserId);
env->CallVoidMethod(m_self, methodId);
static jmethodID startMethodId = env->GetMethodID(klass, "start", "()V");
ASSERT ( startMethodId, () );
env->DeleteLocalRef(klass);
env->CallVoidMethod(m_self, startMethodId);
}
~HttpThread()