Android-Developers

  • Subscribe to our RSS feed.
  • Twitter
  • StumbleUpon
  • Reddit
  • Facebook
  • Digg

Tuesday, 19 July 2011

Debugging Android JNI with CheckJNI

Posted on 10:32 by Unknown

[This post is by Elliott Hughes, a Software Engineer on the Dalvik team — Tim Bray]

Although most Android apps run entirely on top of Dalvik, some use the Android NDK to include native code using JNI. Native code is harder to get right than Dalvik code, and when you have a bug, it’s often a lot harder to find and fix it. Using JNI is inherently tricky (there’s precious little help from the type system, for example), and JNI functions provide almost no run-time checking. Bear in mind also that the developer console’s crash reporting doesn’t include native crashes, so you don’t even necessarily know how often your native code is crashing.

What CheckJNI can do

To help, there’s CheckJNI. It can catch a number of common errors, and the list is continually increasing. In Gingerbread, for example, CheckJNI can catch all of the following kinds of error:

  • Arrays: attempting to allocate a negative-sized array.

  • Bad pointers: passing a bad jarray/jclass/jobject/jstring to a JNI call, or passing a NULL pointer to a JNI call with a non-nullable argument.

  • Class names: passing anything but the “java/lang/String” style of class name to a JNI call.

  • Critical calls: making a JNI call between a GetCritical and the corresponding ReleaseCritical.

  • Direct ByteBuffers: passing bad arguments to NewDirectByteBuffer.

  • Exceptions: making a JNI call while there’s an exception pending.

  • JNIEnv*s: using a JNIEnv* from the wrong thread.

  • jfieldIDs: using a NULL jfieldID, or using a jfieldID to set a field to a value of the wrong type (trying to assign a StringBuilder to a String field, say), or using a jfieldID for a static field to set an instance field or vice versa, or using a jfieldID from one class with instances of another class.

  • jmethodIDs: using the wrong kind of jmethodID when making a Call*Method JNI call: incorrect return type, static/non-static mismatch, wrong type for ‘this’ (for non-static calls) or wrong class (for static calls).

  • References: using DeleteGlobalRef/DeleteLocalRef on the wrong kind of reference.

  • Release modes: passing a bad release mode to a release call (something other than 0, JNI_ABORT, or JNI_COMMIT).

  • Type safety: returning an incompatible type from your native method (returning a StringBuilder from a method declared to return a String, say).

  • UTF-8: passing an invalid Modified UTF-8 byte sequence to a JNI call.

If you’ve written any amount of native code without CheckJNI, you’re probably already wishing you’d known about it. There’s a performance cost to using CheckJNI (which is why it isn’t on all the time for everybody), but it shouldn’t change the behavior in any other way.

Enabling CheckJNI

If you’re using the emulator, CheckJNI is on by default. If you’re working with an Android device, use the following adb command:

adb shell setprop debug.checkjni 1

This won’t affect already-running apps, but any app launched from that point on will have CheckJNI enabled. (Changing the property to any other value or simply rebooting will disable CheckJNI again.) In this case, you’ll see something like this in your logcat output the next time each app starts:

D Late-enabling CheckJNI

If you don’t see this, your app was probably already running; you just need to force stop it and start it again.

Example

Here’s the output you get if you return a byte array from a native method declared to return a String:

W JNI WARNING: method declared to return 'Ljava/lang/String;' returned '[B'
W failed in LJniTest;.exampleJniBug
I "main" prio=5 tid=1 RUNNABLE
I | group="main" sCount=0 dsCount=0 obj=0x40246f60 self=0x10538
I | sysTid=15295 nice=0 sched=0/0 cgrp=default handle=-2145061784
I | schedstat=( 398335000 1493000 253 ) utm=25 stm=14 core=0
I at JniTest.exampleJniBug(Native Method)
I at JniTest.main(JniTest.java:11)
I at dalvik.system.NativeStart.main(Native Method)
I
E VM aborting

Without CheckJNI, you’d just die via SIGSEGV, with none of this output to help you!

New JNI documentation

We’ve also recently added a page of JNI Tips that explains some of the finer points of JNI. If you write native methods, even if CheckJNI isn’t rejecting your code, you should still read that page. It covers everything from correct usage of the JavaVM and JNIEnv types, how to work with native threads, local and global references, dealing with Java exceptions in native code, and much more, including answers to frequently-asked JNI questions.

What CheckJNI can’t do

There are still classes of error that CheckJNI can’t find. Most important amongst these are misuses of local references. CheckJNI can spot if you stash a JNIEnv* somewhere and then reuse it on the wrong thread, but it can’t detect you stashing a local reference (rather than a global reference) and then reusing it in a later native method call. Doing so is invalid, but currently mostly works (at the cost of making life hard for the GC), and we’re still working on getting CheckJNI to spot these mistakes.

We’re hoping to have more checking, including for local reference misuse, in a future release of Android. Start using CheckJNI now, though, and you’ll be able to take advantage of our new checks as they’re added.

Email ThisBlogThis!Share to XShare to FacebookShare to Pinterest
Posted in Debugging, JNI | No comments
Newer Post Older Post Home

0 comments:

Post a Comment

Subscribe to: Post Comments (Atom)

Popular Posts

  • Bring Your Apps into the Classroom, with Google Play for Education
    Posted by Shazia Makhdumi, Head of Strategic EDU Partnerships, Google Play team Google Play for Education has officially launched . It’s an ...
  • A Faster Emulator with Better Hardware Support
    [This post is by Xavier Ducrohet and Reto Meier of the Android engineering team. — Tim Bray.] The Android emulator is a key tool for Android...
  • Powering Chrome to Phone with Android Cloud to Device Messaging
    [This post is by Dave Burke, who's an Engineering Manager 80% of the time. — Tim Bray] Android Cloud to Device Messaging (C2DM) was lau...
  • Android 1.5 is here!
    I've got some good news today: the Android 1.5 SDK, release 1 is ready! Grab it from the download page . For an overview of the new Andr...
  • Memory Analysis for Android Applications
    [This post is by Patrick Dubroy, an Android engineer who writes about programming, usability, and interaction on his personal blog . — Tim B...
  • Preview of Google TV Add-on for the Android SDK
    [This post is by Ambarish Kenghe, who’s a Product Manager for Google TV — Tim Bray] At Google I/O , we announced that Android Market is comi...
  • Android SDK Tools, Revision 20
    [This post is by Xavier Ducrohet , Tech Lead for the Android developer tools] Along with the preview of the Android 4.1 (Jelly Bean) platfo...
  • RenderScript Intrinsics
    Posted by R. Jason Sams , Android RenderScript Tech Lead RenderScript has a very powerful ability called Intrinsics . Intrinsics are built-...
  • In-App Billing on Android Market: Ready for Testing
    [This post is by Eric Chu, Android Developer Ecosystem. —Dirk Dougherty] Back in January we announced our plan to introduce Android Market ...
  • Twitter for Android: A closer look at Android’s evolving UI patterns
    [This post is by Chris Nesladek, Interaction Designer, Richard Fulcher, Interaction Designer, and Virgil Dobjanschi, Software Engineer — Ti...

Categories

  • accessibility
  • Action Bar
  • Administration
  • Android
  • Android 1.5
  • Android 1.6
  • Android 2.0
  • Android 2.1
  • Android 2.2
  • Android 2.3
  • Android 2.3.3
  • Android 3.0
  • Android 3.2
  • Android 4.0
  • Android 4.2
  • Android 4.3
  • Android 4.4
  • Android Design
  • Android Developer Challenge
  • Android Developer Phone
  • Android Market
  • Android SDK
  • Android Studio
  • Animation and Graphics
  • Announcements
  • App Components
  • App Resources
  • Apps
  • Audio
  • Authentication
  • Best Practices
  • Boston
  • Code Day
  • Connectivity
  • Content Provider
  • Cool Stuff
  • Dashboard
  • Daydream
  • Debugging
  • Developer Console
  • Developer Days
  • Developer Labs
  • Developer profiles
  • Developer Story
  • Education
  • Games
  • GCM
  • Gestures
  • Google Analytics
  • Google Cloud Messaging
  • Google Cloud Platform
  • Google I/O
  • Google Play
  • Google Play game services
  • Google Play services
  • Google Services
  • Google Wallet
  • Google+
  • Guidelines
  • How-to
  • Image Processing
  • IME
  • In-app Billing
  • Input methods
  • Intents
  • io2010
  • IO2013
  • JNI
  • Layout
  • Localization
  • Location
  • Location and Sensors
  • London
  • Maps
  • Media and Camera
  • Mountain View
  • Munich
  • NDK
  • Open source
  • OpenGL ES
  • Optimization
  • Performance
  • Photo Sphere
  • Promo Graphics
  • Quality
  • Quick Search Box
  • Renderscript
  • Resources
  • RTL
  • Sample code
  • SDK Tools
  • SDK updates
  • Security
  • Sensors
  • Speech Input
  • Support Library
  • Survey
  • Tablets
  • Tel Aviv
  • Telephony
  • Testing
  • Text and Input
  • Text-to-Speech
  • Tools
  • Touch
  • User Interface
  • User Support
  • WebView
  • Widgets

Blog Archive

  • ►  2013 (45)
    • ►  November (2)
    • ►  October (7)
    • ►  September (2)
    • ►  August (5)
    • ►  July (5)
    • ►  June (4)
    • ►  May (9)
    • ►  April (3)
    • ►  March (2)
    • ►  February (3)
    • ►  January (3)
  • ►  2012 (43)
    • ►  December (5)
    • ►  November (3)
    • ►  October (3)
    • ►  September (1)
    • ►  August (1)
    • ►  July (2)
    • ►  June (5)
    • ►  May (1)
    • ►  April (5)
    • ►  March (6)
    • ►  February (5)
    • ►  January (6)
  • ▼  2011 (67)
    • ►  December (7)
    • ►  November (7)
    • ►  October (5)
    • ►  September (5)
    • ►  August (3)
    • ▼  July (7)
      • Custom Class Loading in Dalvik
      • New Tools For Managing Screen Sizes
      • Multiple APK Support in Android Market
      • Debugging Android JNI with CheckJNI
      • Android 3.2 Platform and Updated SDK tools
      • A New Android Market for Phones
      • New Mode for Apps on Large Screens
    • ►  June (3)
    • ►  May (5)
    • ►  April (6)
    • ►  March (8)
    • ►  February (7)
    • ►  January (4)
  • ►  2010 (72)
    • ►  December (8)
    • ►  November (3)
    • ►  October (4)
    • ►  September (8)
    • ►  August (6)
    • ►  July (9)
    • ►  June (11)
    • ►  May (11)
    • ►  April (2)
    • ►  March (3)
    • ►  February (2)
    • ►  January (5)
  • ►  2009 (63)
    • ►  December (7)
    • ►  November (5)
    • ►  October (5)
    • ►  September (8)
    • ►  August (2)
    • ►  July (1)
    • ►  June (2)
    • ►  May (5)
    • ►  April (12)
    • ►  March (5)
    • ►  February (8)
    • ►  January (3)
  • ►  2008 (40)
    • ►  December (3)
    • ►  November (1)
    • ►  October (4)
    • ►  September (6)
    • ►  August (4)
    • ►  June (1)
    • ►  May (5)
    • ►  April (4)
    • ►  March (5)
    • ►  February (2)
    • ►  January (5)
  • ►  2007 (8)
    • ►  December (3)
    • ►  November (5)
Powered by Blogger.

About Me

Unknown
View my complete profile