summaryrefslogtreecommitdiff
path: root/android/jni
diff options
context:
space:
mode:
authorRobin Watts <robin.watts@artifex.com>2013-04-29 11:52:09 +0100
committerRobin Watts <robin.watts@artifex.com>2013-04-29 13:00:14 +0100
commit7696a4678e1eee59488649ef20f7fbb4d7d3fc0c (patch)
tree095dc8589574d9a16d8d5e20be33045a6cc4310c /android/jni
parentae40ceccb46df6d45e45c40b27f426286a46a7e6 (diff)
downloadmupdf-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.mk3
-rw-r--r--android/jni/Core.mk6
-rw-r--r--android/jni/Core2.mk3
-rw-r--r--android/jni/ThirdParty.mk3
-rw-r--r--android/jni/mupdf.c86
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
+}