diff options
author | Robin Watts <robin.watts@artifex.com> | 2013-04-29 11:52:09 +0100 |
---|---|---|
committer | Robin Watts <robin.watts@artifex.com> | 2013-04-29 13:00:14 +0100 |
commit | 7696a4678e1eee59488649ef20f7fbb4d7d3fc0c (patch) | |
tree | 095dc8589574d9a16d8d5e20be33045a6cc4310c /android/jni | |
parent | ae40ceccb46df6d45e45c40b27f426286a46a7e6 (diff) | |
download | mupdf-7696a4678e1eee59488649ef20f7fbb4d7d3fc0c.tar.xz |
Add Memento build option to Android build. Fix memory leaks.
Following up on a report from a potential customer, fix various places
in mupdf.c where we were leaking memory (devices not freed, context
not properly freed etc).
In order to track this down, I added a Memento build - just do:
ndk-build MEMENTO=1
when building. This only checks for leaks, not for memory overwrites
by default as it uses MEMENTO_LEAKONLY to avoid any possibility of the
android kernel killing stuff for being too slow or using too much
memory.
Diffstat (limited to 'android/jni')
-rw-r--r-- | android/jni/Application.mk | 3 | ||||
-rw-r--r-- | android/jni/Core.mk | 6 | ||||
-rw-r--r-- | android/jni/Core2.mk | 3 | ||||
-rw-r--r-- | android/jni/ThirdParty.mk | 3 | ||||
-rw-r--r-- | android/jni/mupdf.c | 86 |
5 files changed, 83 insertions, 18 deletions
diff --git a/android/jni/Application.mk b/android/jni/Application.mk index 8fec4403..2b2f67c0 100644 --- a/android/jni/Application.mk +++ b/android/jni/Application.mk @@ -23,6 +23,9 @@ endif ifdef V8_BUILD APP_STL := stlport_static endif +ifdef MEMENTO +APP_CFLAGS += -DMEMENTO -DMEMENTO_LEAKONLY +endif # If the ndk is r8b then workaround bug by uncommenting the following line #NDK_TOOLCHAIN_VERSION=4.4.3 diff --git a/android/jni/Core.mk b/android/jni/Core.mk index b3619261..f1312bf2 100644 --- a/android/jni/Core.mk +++ b/android/jni/Core.mk @@ -17,6 +17,9 @@ LOCAL_CFLAGS += -pg -DNDK_PROFILER -O2 endif endif LOCAL_CFLAGS += -DAA_BITS=8 +ifdef MEMENTO +LOCAL_CFLAGS += -DMEMENTO -DMEMENTO_LEAKONLY +endif LOCAL_C_INCLUDES := \ ../thirdparty/jbig2dec \ @@ -141,6 +144,9 @@ LOCAL_SRC_FILES := \ $(MY_ROOT)/xps/xps_util.c \ $(MY_ROOT)/xps/xps_zip.c \ $(MY_ROOT)/cbz/mucbz.c +ifdef MEMENTO + LOCAL_SRC_FILES += $(MY_ROOT)/fitz/memento.c +endif ifdef V8_BUILD ifeq ($(V8_OK),1) LOCAL_SRC_FILES += \ diff --git a/android/jni/Core2.mk b/android/jni/Core2.mk index b8239e18..3c8c1841 100644 --- a/android/jni/Core2.mk +++ b/android/jni/Core2.mk @@ -18,6 +18,9 @@ NDK_APP_CFLAGS := endif endif LOCAL_CFLAGS += -DAA_BITS=8 +ifdef MEMENTO +LOCAL_CFLAGS += -DMEMENTO -DMEMENTO_LEAKONLY +endif LOCAL_C_INCLUDES := \ ../thirdparty/jbig2dec \ diff --git a/android/jni/ThirdParty.mk b/android/jni/ThirdParty.mk index 660c8e9e..e92ca2c4 100644 --- a/android/jni/ThirdParty.mk +++ b/android/jni/ThirdParty.mk @@ -24,6 +24,9 @@ LOCAL_CFLAGS := \ ifdef NDK_PROFILER LOCAL_CFLAGS += -pg -DNDK_PROFILER -O2 endif +ifdef MEMENTO +LOCAL_CFLAGS += -DMEMENTO -DMEMENTO_LEAKONLY +endif LOCAL_MODULE := mupdfthirdparty LOCAL_SRC_FILES := \ diff --git a/android/jni/mupdf.c b/android/jni/mupdf.c index 95d2e10a..2282d7dc 100644 --- a/android/jni/mupdf.c +++ b/android/jni/mupdf.c @@ -249,8 +249,11 @@ static void alerts_fin(globals *glo) static globals *get_globals(JNIEnv *env, jobject thiz) { globals *glo = (globals *)(void *)((*env)->GetLongField(env, thiz, global_fid)); - glo->env = env; - glo->thiz = thiz; + if (glo != NULL) + { + glo->env = env; + glo->thiz = thiz; + } return glo; } @@ -430,6 +433,10 @@ JNI_FN(MuPDFCore_openBuffer)(JNIEnv * env, jobject thiz) } LOGE("Done!"); } + fz_always(ctx) + { + fz_close(stream); + } fz_catch(ctx) { LOGE("Failed: %s", ctx->error->message); @@ -655,19 +662,18 @@ JNI_FN(MuPDFCore_drawPage)(JNIEnv *env, jobject thiz, jobject bitmap, pc->page_list = fz_new_display_list(ctx); dev = fz_new_list_device(ctx, pc->page_list); fz_run_page_contents(doc, pc->page, dev, &fz_identity, NULL); + fz_free_device(dev); + dev = NULL; } if (pc->annot_list == NULL) { fz_annot *annot; - if (dev) - { - fz_free_device(dev); - dev = NULL; - } pc->annot_list = fz_new_display_list(ctx); dev = fz_new_list_device(ctx, pc->annot_list); for (annot = fz_first_annot(doc, pc->page); annot; annot = fz_next_annot(doc, annot)) fz_run_annot(doc, pc->page, annot, dev, &fz_identity, NULL); + fz_free_device(dev); + dev = NULL; } bbox.x0 = patchX; bbox.y0 = patchY; @@ -717,9 +723,13 @@ JNI_FN(MuPDFCore_drawPage)(JNIEnv *env, jobject thiz, jobject bitmap, fz_drop_pixmap(ctx, pix); LOGE("Rendered"); } - fz_catch(ctx) + fz_always(ctx) { fz_free_device(dev); + dev = NULL; + } + fz_catch(ctx) + { LOGE("Render failed"); } @@ -825,17 +835,17 @@ JNI_FN(MuPDFCore_updatePageInternal)(JNIEnv *env, jobject thiz, jobject bitmap, pc->page_list = fz_new_display_list(ctx); dev = fz_new_list_device(ctx, pc->page_list); fz_run_page_contents(doc, pc->page, dev, &fz_identity, NULL); + fz_free_device(dev); + dev = NULL; } if (pc->annot_list == NULL) { - if (dev) { - fz_free_device(dev); - dev = NULL; - } pc->annot_list = fz_new_display_list(ctx); dev = fz_new_list_device(ctx, pc->annot_list); for (annot = fz_first_annot(doc, pc->page); annot; annot = fz_next_annot(doc, annot)) fz_run_annot(doc, pc->page, annot, dev, &fz_identity, NULL); + fz_free_device(dev); + dev = NULL; } bbox.x0 = patchX; @@ -885,9 +895,13 @@ JNI_FN(MuPDFCore_updatePageInternal)(JNIEnv *env, jobject thiz, jobject bitmap, LOGE("Rendered"); } - fz_catch(ctx) + fz_always(ctx) { fz_free_device(dev); + dev = NULL; + } + fz_catch(ctx) + { LOGE("Render failed"); } @@ -1030,6 +1044,7 @@ JNI_FN(MuPDFCore_hasOutlineInternal)(JNIEnv * env, jobject thiz) globals *glo = get_globals(env, thiz); fz_outline *outline = fz_load_outline(glo->doc); + fz_free_outline(glo->ctx, outline); return (outline == NULL) ? JNI_FALSE : JNI_TRUE; } @@ -1043,6 +1058,7 @@ JNI_FN(MuPDFCore_getOutlineInternal)(JNIEnv * env, jobject thiz) fz_outline *outline; int nItems; globals *glo = get_globals(env, thiz); + int ret; olClass = (*env)->FindClass(env, PACKAGENAME "/OutlineItem"); if (olClass == NULL) return NULL; @@ -1058,9 +1074,11 @@ JNI_FN(MuPDFCore_getOutlineInternal)(JNIEnv * env, jobject thiz) NULL); if (arr == NULL) return NULL; - return fillInOutlineItems(env, olClass, ctor, arr, 0, outline, 0) > 0 + ret = fillInOutlineItems(env, olClass, ctor, arr, 0, outline, 0) > 0 ? arr :NULL; + fz_free_outline(glo->ctx, outline); + return ret; } JNIEXPORT jobjectArray JNICALL @@ -1606,6 +1624,8 @@ static void close_doc(globals *glo) fz_close_document(glo->doc); glo->doc = NULL; + fz_free_context(glo->ctx); + glo->ctx = NULL; } JNIEXPORT void JNICALL @@ -1613,12 +1633,19 @@ JNI_FN(MuPDFCore_destroying)(JNIEnv * env, jobject thiz) { globals *glo = get_globals(env, thiz); + if (glo == NULL) + return; LOGI("Destroying"); - close_doc(glo); fz_free(glo->ctx, glo->current_path); glo->current_path = NULL; + close_doc(glo); free(glo); - +#ifdef MEMENTO + LOGI("Destroying dump start"); + Memento_listBlocks(); + Memento_stats(); + LOGI("Destroying dump end"); +#endif #ifdef NDK_PROFILER // Apparently we should really be writing to whatever path we get // from calling getFilesDir() in the java part, which supposedly @@ -1686,7 +1713,11 @@ JNI_FN(MuPDFCore_getPageLinksInternal)(JNIEnv * env, jobject thiz, int pageNumbe } arr = (*env)->NewObjectArray(env, count, linkInfoClass, NULL); - if (arr == NULL) return NULL; + if (arr == NULL) + { + fz_drop_link(glo->ctx, list); + return NULL; + } count = 0; for (link = list; link; link = link->next) @@ -1726,11 +1757,16 @@ JNI_FN(MuPDFCore_getPageLinksInternal)(JNIEnv * env, jobject thiz, int pageNumbe continue; } - if (linkInfo == NULL) return NULL; + if (linkInfo == NULL) + { + fz_drop_link(glo->ctx, list); + return NULL; + } (*env)->SetObjectArrayElement(env, arr, count, linkInfo); (*env)->DeleteLocalRef(env, linkInfo); count++; } + fz_drop_link(glo->ctx, list); return arr; } @@ -2361,3 +2397,17 @@ JNI_FN(MuPDFCore_saveInternal)(JNIEnv * env, jobject thiz) } } } + +JNIEXPORT void JNICALL +JNI_FN(MuPDFCore_dumpMemoryInternal)(JNIEnv * env, jobject thiz) +{ + globals *glo = get_globals(env, thiz); + fz_context *ctx = glo->ctx; + +#ifdef MEMENTO + LOGE("dumpMemoryInternal start"); + Memento_listNewBlocks(); + Memento_stats(); + LOGE("dumpMemoryInternal end"); +#endif +} |