vincentjames501 / libvorbis-libogg-android

JNI Android wrapper for encoding and decoding ogg/vorbis bitstreams
67 stars 39 forks source link

JNI Local Reference #13

Open n00bman opened 9 years ago

n00bman commented 9 years ago

Hi!

Some days ago I'm trying to use this library for my project. When I build this lib with lates ndk r10 then I've got some errors like "invalid local reference access". See http://android-developers.blogspot.ie/2011/11/jni-local-reference-changes-in-ics.html

Ice Cream Sandwich features a JNI bug compatibility mode so that as long as your AndroidManifest.xml’s targetSdkVersion is less than Ice Cream Sandwich, your code is exempt. But as soon as you update your >targetSdkVersion, your code needs to be correct. ... In the old system, where local references were direct pointers, local references were never really invalidated. That meant you could use a local reference indefinitely, even if you’d explicitly called >DeleteLocalRef() on it.

My project targetSdkVersion is set to 21 api (Ice Cream Sandwich is 14 api).

In current Application.mk file no "APP_PLATFORM" string, so build used max avaliable api from platforms/ dir in android-ndk-r10d. It is "android-21".

Let's see lib project source.

org_xiph_vorbis_encoder_VorbisEncoder.c

https://github.com/vincentjames501/libvorbis-libogg-android/blob/master/jni/libvorbis-jni/org_xiph_vorbis_encoder_VorbisEncoder.c#L58 https://github.com/vincentjames501/libvorbis-libogg-android/blob/master/jni/libvorbis-jni/org_xiph_vorbis_encoder_VorbisEncoder.c#L65

There is code

jbyteArray jByteArray = (*env)->NewByteArray(env, bytes);
...
(*env)->DeleteLocalRef(env, jByteArray);

But this array is not using anywhere. Coz of this commit

https://github.com/vincentjames501/libvorbis-libogg-android/commit/df94ad0c4868f4f31cff2d7bbdb153666c88cbe2#diff-14780fb01dc7b653aaa48547d7810e1fL76

And we can delete NewByteArray and DeleteLocalRef lines for this array (see lates fix https://github.com/vincentjames501/libvorbis-libogg-android/commit/18e49d55d66bc295d8ef835d906d757908d5f0e1)

int startEncoding(JNIEnv *env, jclass *cls_ptr, jlong *sampleRate_ptr, jlong *channels_ptr, jfloat *quality_ptr, jlong *bitrate_ptr, jobject *encoderDataFeed_ptr, int type) {

...

//Create a new java byte array to pass to the data feed method
    jbyteArray jByteArrayBuffer = (*env)->NewByteArray(env, READ*4);

    //Create a new java byte buffer to write to
    jbyteArray jByteArrayWriteBuffer = (*env)->NewByteArray(env, READ*8);

    //Find our java classes we'll be calling
    jclass encoderDataFeedClass = (*env)->FindClass(env, "org/xiph/vorbis/encoder/EncodeFeed");

...

writeVorbisDataToEncoderDataFeed(env, &encoderDataFeed, &writeVorbisDataMethodId, og.header, og.header_len, &jByteArrayWriteBuffer);

...
 //Clean up encode buffers
    (*env)->DeleteLocalRef(env, jByteArrayBuffer);
    (*env)->DeleteLocalRef(env, jByteArrayWriteBuffer);

Problem is here:

  1. There is no DeleteLocalRef for encoderDataFeedClass. We should add it.
(*env)->DeleteLocalRef(env, encoderDataFeedClass)
  1. This code makes error "local reference access error".
(*env)->DeleteLocalRef(env, jByteArrayBuffer) 
(*env)->DeleteLocalRef(env, jByteArrayWriteBuffer)

There is no local ref for jByteArrayBuffer and jByteArrayWriteBuffer! I'd know why, but GC clear this reference and I've got jni errors on this lines. There is also other file org_xiph_vorbis_decoder_VorbisDecoder.c with the same lines

    //Clean up our buffers
    (*env)->DeleteLocalRef(env, jByteArrayReadBuffer);
    (*env)->DeleteLocalRef(env, jShortArrayWriteBuffer);

but theres is no jni errors.

I can comment DeleteLocalRef lines in org_xiph_vorbis_encoder_VorbisEncoder.c but don't think it's correct. Can you help me to fix this problems?

vincentjames501 commented 9 years ago

Can you submit a pull request for the known issues and create a new issue with your question? I'm not sure which piece it is you need help with exactly.

NickoftheSouth commented 9 years ago

OK So I've just been dealing with the same issue. I'm only using this for Encoding, so I'm not sure about decoding. I was seeing a crash on newer versions of android when stopping the straem. I narrowed down the issue to these lines at the end of the startEncoding() method in org_xiph_vorbis_encoder_VorbisEncoder.c

(*env)->DeleteLocalRef(env, jByteArrayBuffer);
(*env)->DeleteLocalRef(env, jByteArrayWriteBuffer);

this was casing a crash. I commented out the lines and extended on n00bmans sugestion replacing the lines with:

//(*env)->DeleteLocalRef(env, jByteArrayBuffer);
//(*env)->DeleteLocalRef(env, jByteArrayWriteBuffer);
(*env)->DeleteLocalRef(env, encoderDataFeedClass);
(*env)->DeleteLocalRef(env, encoderDataFeed);

Not too sure about the last ones, but it seems to work without complaint.

hope this helps