NDK技巧
- 加快ndk-build编译速度
NDK编译时加上-j参数,如:
1
ndk-build -j4 # -j4,让make最多允许4个编译命令同时执行
测试后编译速度至少可以提高一倍
native崩溃分析
定位crash错误位置
首先我们要先把Logcat里的show only selected application选项改成No Filters, 这时就能看到系统打印出的DEBUG信息. 在DEBUG信息里找到backtrace, 这段就是系统给出的造成崩溃的信息, 但仅仅给出了是哪个函数, 而没有准确给出是那一行代码造成的崩溃. 记下#00 pc 00013122(红框3)这个信息, 这个信息就是用来定位崩溃代码的地址
1 | 12-27 10:45:41.580 6189-6761/com.wodekouwei.demo E/HwDecodeWrapper: dequeueOutputBuffer = -1 |
想要准确定位崩溃代码的地址的话我们就需要用到ndk工具包里的adrr2line这个工具了 首先先找到这个工具, linux系统这个工具在如下位置
1 | /home/gavinandre/Documents/Android/android-sdk-linux/ndk-bundle/toolchains/arm-linux-androideabi-4.9/prebuilt/linux-x86_64/bin/arm-linux-androideabi-addr2line |
在该目录下做个软链接后就能在任何目录使用这个命令了
1 | sudo ln -s arm-linux-androideabi-addr2line /usr/local/bin/addr2line |
找到造成崩溃的so文件地址, 在app目录下搜索so文件
1 | find . -name "liboarp-lib.so" ✘ |
可以看到android studio编译后生成了许多so文件, 以我的经验正确的so文件一般是这个文件:./srsrtmpplayer/build/intermediates/transforms/mergeJniLibs/debug/0/lib/armeabi-v7a/liboarp-lib.so
然后就可以使用addrline命令了, 格式是addr2line -e 文件位置 崩溃地址:
1 | addr2line -e ./srsrtmpplayer/build/intermediates/transforms/mergeJniLibs/debug/0/lib/armeabi-v7a/liboarp-lib.so 000ccb4c |
如果so文件正确的话会打印如下信息,oar_player_gl_thread.c就是崩溃的cpp文件, 152, 然后检查下定位出来的位置是否在DEBUG信息里给出的函数里
1 | oar_player_gl_thread.c:152 |
如果so文件错误的话会打印问号或者一个不对的位置, 这时就要换so文件多尝试了
C回调JAVA
c中返回一个字符串
1
(*env)->NewStringUTF(env,"Huazi 华仔");
c中返回一个数组
1
2
3
4
5
6
7
8
9
10.....................
int i = 0;
jintArray array;
array =(*env)->NewIntArray(env,8);
for(;i<8;i++)
// 赋值成 0 ~ 7
(*env)->SetObjectArrayElement(env,array,i,i);
}
return array;c中使用调用传入的参数是数组array 是传入的数组
1
2
3
4
5
6
7
8
9.........
int sum =0, i;
int len = (*env)->GetArrayLength(env,array);
jint *element =(*env)->GetIntArrayElement(env,array,0);
for(i=0;i<len;i++)
{
sum+= *(element+i);
}
return sum;c中调用java中类的方法 没有参数 只有返回值String
1
2
3
4
5
6
7//()Ljava/lang/String;" 表示参数为空 返回值是String类型
JNIEXPORT jstring JNICALLJava_com_huazi_Demo_getCallBack(JNIENV env,jobject object){
jmethodID mid;
jclass cls =(*env)->FindClass(env,"com/huazi/Demo"); //后面是包名+类名
mid =(*env)->GetMethodID(env,cls,"TestMethod","()Ljava/lang/String;");//TestMethod java中的方法名
jstring msg =(*env)->CallObjectMethod(env,object,mid); //object 注意下是jni传过来的jobject
return msg;c中调用java中类的静态方法 没有参数 只有返回值String
1
2
3
4
5
6
7
8//@"()Ljava/lang/String;" 表示参数为空 返回值是String类型
JNIEXPORT jstring JNICALLJava_com_huazi_Demo_getCallBack(JNIENV env,jobject object){
jmethodID mid;
jclass cls =(*env)->FindClass(env,"com/huazi/Demo"); //后面是包名+类名
mid =(*env)->GeStatictMethodID(env,cls,"TestMethod","()Ljava/lang/String;");// TestMethod java中的方法名
jstring msg =(*env)->CallStaticObjectMethod(env,cls,mid); //object 注意下是jni传过来的jobject
return msg;
}
There are multiple color attachment points (GL_COLOR_ATTACHMENT0,…, GL_COLOR_ATTACHMENTn), one depth attachment point (GL_DEPTH_ATTACHMENT), and one stencil attachment point (GL_STENCIL_ATTACHMENT) in a framebuffer object. The number of color attachment points is implementation dependent, but each FBO must have at least one color attachement point. You can query the maximum number of color attachement points with GL_MAX_COLOR_ATTACHMENTS, which are supported by a graphics card. The reason that a FBO has multiple color attachement points is to allow to render the color buffer to multiple destinations at the same time. This “multiple render targets” (MRT) can be accomplished by GL_ARB_draw_buffers extension. Notice that the framebuffer object itself does not have any image storage(array) in it, but, it has only multiple attachment points.
在一个帧缓存对象中有多个颜色关联点(GL_COLOR_ATTACHMENT0_EXT,…,GL_COLOR_ATTACHMENTn_EXT),一个深度关联点(GL_DEPTH_ATTACHMENT_EXT),和一个模板关联点(GL_STENCIL_ATTACHMENT_EXT)。每个FBO中至少有一个颜色关联点,其数目与实体显卡相关。可以通过GL_MAX_COLOR_ATTACHMENTS_EXT来查询颜色关联点的最大数目。FBO有多个颜色关联点的原因是这样可以同时将颜色而换成渲染到多个FBO关联区。这种“多渲染目标”(multiple rendertargets,MRT)可以通过GL_ARB_draw_buffers扩展实现。需要注意的是:FBO本身并没有任何图像存储区,只有多个关联点。









