У меня есть кеш, реализованный в c ++ с использованием multimap, а затем я просматриваю кеш и возвращаю совпадающие целочисленные значения в виде массива в код Java.
Проблема, с которой я сталкиваюсь, заключается в постепенном старом поколенииполностью заполняется и запускает непрерывный полный GC оттуда. Я обнаружил, что просто возвращение статического массива приводит к тому, что старое поколение периодически заполняется и запускает полный сборщик мусора. В конце концов при высокой нагрузке система будет создавать дамп памяти.
Код похож на Java
for(JavaObject o: javaOjctes){
int[] values = cache.get(o.getkey1,o.getkey2,o.getkeyType[]);
//further processing
}
, а на стороне C ++ у меня есть CacheImpl.cpp
JNIEXPORT jintArray JNICALL Java_com_test_cache_CacheService_get(JNIEnv *env, jobject thisObject, jstring key1,jstring key2,jobjectArray keyTypes){
const char *key1Value = (env)->GetStringUTFChars(key1,NULL);
env->ReleaseStringUTFChars(key1,key1Value);
//if(key1Value == NULL)
//return NULL;
const char *key2Value = (env)->GetStringUTFChars(key2,NULL);
//if(key2Value == NULL)
//return NULL;
string key2_str(key2value);
env->ReleaseStringUTFChars(key2,key2Value);
jsize length = env->GetArrayLength(keyTypes);
if(length == 0)
return NULL;
// I’m managing the C++ cache from Java side, so getting the
// reference of native cache from Java
jclass CacheService = env->GetObjectClass(thisObject);
Cache* cache= (Cache*) env->GetStaticLongField(CacheService,getCacheField(env,thisObject));
env->DeleteLocalRef(CacheService);
list<int> result;
for(int index=0;index<length;index++){
jstring keyType =(jstring) env->GetObjectArrayElement(keyTypes,index);
const char *key_type_str=env->GetStringUTFChars(keyType,NULL);
string key_type(key_type_str);
env->ReleaseStringUTFChars(keyType,key_type_str);
// Cache.cpp code is given below
list<int> intermediate=cache->get(key2_str+key_type,key1Value);
result.merge(intermediate);
intermediate=cache->get(key_type,key1Value);
result.merge(intermediate);
}
env->ReleaseStringUTFChars(key1,key1Value);
// I would return result list from below code
// For testing I commented all of the above code and
// tested with only below code. I could see Old gen
// Keep growing and GC spikes
jintArray Ids=env->NewIntArray(50);
if(Ids == NULL){
return NULL;
}
jint return_Array[50];
int j=0;
for(j=0; j<50 ;j++){
return_Array[j]=j;
}
env->SetIntArrayRegion(Ids,0,50,return_Array);
//env->DeleteLocalRef(Ids);
return Ids;
иКод Cache.cpp выглядит следующим образом:
shared_ptr<multimap<string, SomeObject> > Cache::cacheMap;
list<int> Cache::get(string key,const char* key1Value){
SomeObject value;
list<int> IDs;
shared_ptr<multimap<string, SomeObject> > readMap=atomic_load(&cacheMap);
pair<mapIterator,mapIterator> result=readMap->equal_range(key);
for(auto iterator=result.first; iterator!=result.second; iterator++){
value=iterator->second;
if(!(value.checkID(key1Value))){
IDs.push_front(value.getID(key1Value));
}
}
return IDs;
}
В приведенном выше коде я предполагаю, что массив Ids
jintArray Ids=env->NewIntArray(50);
не удаляется, поэтому я попытался
//env->DeleteLocalRef(Ids);
Это не работает, поскольку пустой массив будет возвращен на стороне Java.
Как описано в комментариях к коду, я закомментировал весь код, за исключением возврата статического массива в Java. Я мог видеть, что Старое Поколение постепенно заполнялось, вызывая Полный GC, который, я считаю, является проблемой медленной утечки. У меня медленная утечка в этом потоке поиска в кеше. Я что-то пропустил?
Спасибо, Радж