How to query ReferenceTable size?

1,019 views
Skip to first unread message

blindfold

unread,
Jul 5, 2009, 3:55:22 PM7/5/09
to android-ndk
I have a question about debugging facilities for JNI. Is there some
means to output the ReferenceTable size while the program is running?
Having to wait until a crash occurs makes debugging awfully hard, and
I need to isolate which parts and lines of my code are growing the
ReferenceTable.

My app runs functionally fine using JNI to replace some CPU-intensive
parts. However, after a few minutes it crashes with

WARN/dalvikvm(7950): ReferenceTable overflow (max=51200)
WARN/dalvikvm(7950): Last 10 entries in JNI global reference table:
WARN/dalvikvm(7950): 51190: 0x43542b60 cls=[I (276 bytes)
WARN/dalvikvm(7950): 51191: 0x43542c78 cls=[I (276 bytes)
WARN/dalvikvm(7950): 51192: 0x43542d90 cls=[I (276 bytes)
WARN/dalvikvm(7950): 51193: 0x43542ea8 cls=[I (276 bytes)
WARN/dalvikvm(7950): 51194: 0x43542fc0 cls=[I (276 bytes)
WARN/dalvikvm(7950): 51195: 0x435430d8 cls=[I (276 bytes)
WARN/dalvikvm(7950): 51196: 0x435431f0 cls=[I (276 bytes)
WARN/dalvikvm(7950): 51197: 0x43543308 cls=[I (276 bytes)
WARN/dalvikvm(7950): 51198: 0x43543420 cls=[I (276 bytes)
WARN/dalvikvm(7950): 51199: 0x43543538 cls=[I (276 bytes)
WARN/dalvikvm(7950): JNI global reference table summary (51200
entries):
WARN/dalvikvm(7950): 127 of Ljava/lang/Class; 164B (49 unique)
WARN/dalvikvm(7950): 1 of Ljava/lang/String; 28B
WARN/dalvikvm(7950): 65 of [B 16020B (1 unique)
WARN/dalvikvm(7950): 67 of [B 230420B (1 unique)
WARN/dalvikvm(7950): 50187 of [I 276B (257 unique)
WARN/dalvikvm(7950): 260 of [I 1044B (3 unique)
WARN/dalvikvm(7950): 268 of [I 32788B (4 unique)
WARN/dalvikvm(7950): 130 of [I 64020B (1 unique)
WARN/dalvikvm(7950): 72 of Ljava/lang/ref/WeakReference; 28B (72
unique)
WARN/dalvikvm(7950): 10 of Ljava/lang/ref/WeakReference; 36B (10
unique)
...
WARN/dalvikvm(7950): Memory held directly by native code is 526496
bytes
ERROR/dalvikvm(7950): Failed adding to JNI global ref table (51200
entries)

Apparently I am not properly cleaning up despite ample use of
DeleteLocalRef, ReleaseIntArrayElements etc, and I am unaware of
creating more than a few global references (trying to delete
candidates just gives me "DeleteGlobalRef(xxx) failed to find entry"
messages).

Thanks

blindfold

unread,
Jul 6, 2009, 6:12:26 AM7/6/09
to android-ndk
Never mind, my problem was that the isCopy conditional release in

GetIntArrayElements(,,&isCopy);
...
if (isCopy) ReleaseIntArrayElements(,,,JNI_ABORT);

did not work. Problem solved, although it would still be great to have
a means to output the ReferenceTable size when strange things happen.

Regards

fadden

unread,
Jul 6, 2009, 2:25:11 PM7/6/09
to android-ndk
On Jul 6, 3:12 am, blindfold <seeingwithso...@gmail.com> wrote:
> Never mind, my problem was that the isCopy conditional release in
>
> GetIntArrayElements(,,&isCopy);
> ...
> if (isCopy) ReleaseIntArrayElements(,,,JNI_ABORT);
>
> did not work. Problem solved, although it would still be great to have
> a means to output the ReferenceTable size when strange things happen.

You MUST release everything you get, whether it's a copy or not.
Please see the dalvik/vm/jni-tips.html document:

http://android.git.kernel.org/?p=platform/dalvik.git;a=blob_plain;f=docs/jni-tips.html;hb=HEAD

If you have CheckJNI enabled, which is HIGHLY RECOMMENDED, the global
references table is capped at 2000 and you will blow up much sooner.

blindfold

unread,
Jul 6, 2009, 6:52:55 PM7/6/09
to android-ndk
Thank you for the useful document reference, fadden! Had not seen it
before. Indeed I only realized later that I must always release, also
when data is pinned. My app now ran for at least ten minutes without
crashing, and the added performance through the NDK finally enables me
to implement some slightly more refined algorithms that I used to
apply only under Win32 on netbooks. The embedded .so approach is quite
elegant, and I hope this will extend to x86 and other mainstream CPUs
and accelerators such that one and the same APK can serve them all.
Overall I am pleased with the NDK.

BTW, the link to http://android.git.kernel.org/embedded-vm-control.html
(Controlling the Embedded VM) in
is currently a dead link, and apparently one has to go to
http://android.git.kernel.org/?p=platform/dalvik.git;a=blob_plain;f=docs/embedded-vm-control.html;hb=HEAD

Regards

fadden

unread,
Jul 6, 2009, 7:45:59 PM7/6/09
to android-ndk
On Jul 6, 3:52 pm, blindfold <seeingwithso...@gmail.com> wrote:
> BTW, the link tohttp://android.git.kernel.org/embedded-vm-control.html
> (Controlling the Embedded VM) inhttp://android.git.kernel.org/?p=platform/dalvik.git;a=blob_plain;f=d...
> is currently a dead link, and apparently one has to go tohttp://android.git.kernel.org/?p=platform/dalvik.git;a=blob_plain;f=d...

Yeah, those pages are not really meant to be browsed out of gitweb.
Links between documents don't work, and your browser won't find the
CSS pairing for the DEX docs. It is, however, much more convenient
than downloading the git repository if you don't already have it.

The "JNI Tips" document grew out of questions and mistakes made by the
Android team at Google. It's basically the list of stuff that
everybody gets wrong. :-)

blindfold

unread,
Jul 11, 2009, 8:21:10 AM7/11/09
to android-ndk
Excellent fadden! I successfully set CheckJNI by setting its property
in /data/local.prop, and after rebooting my ADP and starting my app
with Eclipse it properly started with the LogCat message "CheckJNI is
ON".

However, despite extra precautions for failing native code allocations
(in case the device would be short on memory), I found that GREF was
on average still slowly increasing, by something like 100 or 200 for
every 100 iterations in my app. I'm strongly suspecting that this is
not due to a bug in my native code. In fact I still see it when I
disable my native code calls, and the unexplained GREF growth
disappears if I replace my (non-native, pure Android) AudioTrack calls
by my older MediaPlayer workaround that writes audio to flash memory
and plays from there. Now my use of AudioTrack/MediaPlayer is
completely separate from my JNI use.

Is there a known reference release bug in the Cupcake implementation
of AudioTrack? The GREF messages are not fine-grained enough to do
more detailed checking than looking at GREF increments/decrements by
100. I'm reminded of a similar discussion at

http://groups.google.com/group/android-developers/browse_thread/thread/2b799814c99d8e2c/

(although in an earlier observation I only encountered the issue on
the emulator).

Thanks

blindfold

unread,
Jul 11, 2009, 9:53:45 AM7/11/09
to android-ndk
The fact that -Xcheck:jni is by default active on the emulator but not
on the phone now explains the earlier AudioTrack GREF behavior
discrepancy between emulator and phone. I have now filed a bug report
on AudioTrack and its GREF growth at http://code.google.com/p/android/issues/detail?id=3234

On Jul 11, 2:21 pm, blindfold <seeingwithso...@gmail.com> wrote:
> Excellent fadden! I successfully set CheckJNI by setting its property
> in /data/local.prop, and after rebooting my ADP and starting my app
> with Eclipse it properly started with the LogCat message "CheckJNI is
> ON".
>
> However, despite extra precautions for failing native code allocations
> (in case the device would be short on memory), I found that GREF was
> on average still slowly increasing, by something like 100 or 200 for
> every 100 iterations in my app. I'm strongly suspecting that this is
> not due to a bug in my native code. In fact I still see it when I
> disable my native code calls, and the unexplained GREF growth
> disappears if I replace my (non-native, pure Android) AudioTrack calls
> by my older MediaPlayer workaround that writes audio to flash memory
> and plays from there. Now my use of AudioTrack/MediaPlayer is
> completely separate from my JNI use.
>
> Is there a known reference release bug in the Cupcake implementation
> of AudioTrack? The GREF messages are not fine-grained enough to do
> more detailed checking than looking at GREF increments/decrements by
> 100. I'm reminded of a similar discussion at
>
> http://groups.google.com/group/android-developers/browse_thread/threa...
Reply all
Reply to author
Forward
0 new messages