這家公司很小,小到就一個大一點的辦公室,以至於面試時會議室有人開會,所以我是在陽臺上面的。
1.malloc,calloc有什麼區別?
void Test( void )
{
char *str = (char *) malloc( 100 );
strcpy( str, "hello" );
free( str );
str = null;
}
malloc調用形式爲(類型*)malloc(size):在內存的動態存儲區中分配一塊長度爲“size”字節的連續區域,返回該區域的首地址。
calloc調用形式爲(類型*)calloc(n,size):在內存的動態存儲區中分配n塊長度爲“size”字節的連續區域,返回首地址。
2.JNI層如何調用java層函數?
說實話,這個問題並沒有回答的很好,可能做過,但根本不記得了!
https://blog.csdn.net/hty1053240123/article/details/52126386
個人認爲第二篇博客參考的比較好
package com.example.ndkcallback;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
public class DataProvider {
//C調用java空方法
public void helloFromJava(){
System.out.println("哈哈哈 我被調用了");
}
//C調用java中的帶兩個int參數的方法
public int Add(int x,int y){
int result=x+y;
System.out.println("result:"+result);
return result;
}
//C調用java中參數爲string的方法
public void printString(String s){
System.out.println(s);
}
public static void demo(){
System.out.println("哈哈哈,我是靜態方法");
}
public native void callMethod1();
public native void callMethod2();
public native void callMethod3();
public native void callMethod4();
public native void callMethod5();
}
配置build和Androidl.mk, javah生成頭文件
#include "com_example_ndkcallback_DataProvider.h"
JNIEXPORT void JNICALL Java_com_example_ndkcallback_DataProvider_callMethod1
(JNIEnv * env, jobject jobject){
/*
*
Class<?> forName = Class.forName("com.example.ndkcallback.DataProvider");
Method declaredMethod = forName.getDeclaredMethod("helloFromJava", new Class[]{});
declaredMethod.invoke(forName.newInstance(), new Object[]{});
*
*
*/
///jclass (*FindClass)(JNIEnv*, const char*);
jclass clazz=(*env)->FindClass(env,"com/example/ndkcallback/DataProvider");
// jmethodID (*GetMethodID)(JNIEnv*, jclass, const char*, const char*);
// 方法簽名 參數和返回值
jmethodID methodId=(*env)->GetMethodID(env,clazz,"helloFromJava","()V");
// void (*CallVoidMethod)(JNIEnv*, jobject, jmethodID, ...);
(*env)->CallVoidMethod(env,jobject,methodId);
}
JNIEXPORT void JNICALL Java_com_example_ndkcallback_DataProvider_callMethod2
(JNIEnv * env, jobject jobject){
jclass clazz=(*env)->FindClass(env,"com/example/ndkcallback/DataProvider");
jmethodID methodId=(*env)->GetMethodID(env,clazz,"Add","(II)I");
// jint (*CallIntMethod)(JNIEnv*, jobject, jmethodID, ...);
(*env)->CallIntMethod(env,jobject,methodId,3,5);
}
JNIEXPORT void JNICALL Java_com_example_ndkcallback_DataProvider_callMethod3
(JNIEnv * env, jobject jobject){ // 參數 object 就是native方法所在的類
jclass clazz=(*env)->FindClass(env,"com/example/ndkcallback/DataProvider");
jmethodID methodId=(*env)->GetMethodID(env,clazz,"printString","(Ljava/lang/String;)V");
// jint (*CallIntMethod)(JNIEnv*, jobject, jmethodID, ...);
jstring str=(*env)->NewStringUTF(env,"hello");
(*env)->CallVoidMethod(env,jobject,methodId,str);
}
JNIEXPORT void JNICALL Java_com_example_ndkcallback_DataProvider_callMethod4
(JNIEnv * env, jobject j){
jclass clazz=(*env)->FindClass(env,"com/example/ndkcallback/MainActivity");
// jmethodID (*GetMethodID)(JNIEnv*, jclass, const char*, const char*);
// 方法簽名 參數和返回值
jmethodID methodId=(*env)->GetMethodID(env,clazz,"helloFromJava","()V");
// void (*CallVoidMethod)(JNIEnv*, jobject, jmethodID, ...);
// 需要創建DataProvider的 對象
// jobject (*AllocObject)(JNIEnv*, jclass);
jobject obj=(*env)->AllocObject(env,clazz); // new MainActivity();
(*env)->CallVoidMethod(env,obj,methodId);
}
JNIEXPORT void JNICALL Java_com_example_ndkcallback_DataProvider_callMethod5
(JNIEnv * env, jobject j){
jclass clazz=(*env)->FindClass(env,"com/example/ndkcallback/DataProvider");
// jmethodID (*GetStaticMethodID)(JNIEnv*, jclass, const char*, const char*);
jmethodID methodid=(*env)->GetStaticMethodID(env,clazz,"demo","()V");
//void (*CallStaticVoidMethod)(JNIEnv*, jclass, jmethodID, ...);
(*env)->CallStaticVoidMethod(env,clazz,methodid);
}
上面代碼大家需要注意一點:()V代表參數爲空,返回爲void;(Ljava/lang/String;)V代表參數爲String類型,返回爲void;(II)I代表參數值爲(int,int)返回值也爲int。
3.OKHttp支持哪些版本Http協議?
支持 spdy、http2.0
4.自定義相機用的camera幾?
https://blog.csdn.net/dongxianfei/article/details/91445918
比較camera和camera2的區別!感覺問題都比較偏。
5.JNI方法註冊方式,你用的哪一種?(*****)
分爲靜態註冊和動態註冊
https://www.jianshu.com/p/18e3a9e9cec9
靜態註冊
原理:根據函數名來建立 java 方法與 JNI 函數的一一對應關係;
實現流程:
編寫 java 代碼;
利用 javah 指令生成對應的 .h 文件;
對 .h 中的聲明進行實現;
弊端:
編寫不方便,JNI 方法名字必須遵循規則且名字很長;
編寫過程步驟多,不方便;
程序運行效率低,因爲初次調用native函數時需要根據根據函數名在JNI層中搜索對應的本地函數,然後建立對應關係,這個過程比較耗時;
typedef struct {
const char* name; // Java方法的名字
const char* signature; //Java方法的簽名信息
void* fnPtr; //JNI中對應的方法指針
} JNINativeMethod;
#include <jni.h>
#include <string>
#include<android/log.h>
#define TAG "test-jni"
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO,TAG ,__VA_ARGS__) // 定義LOGI類型
/**
* 靜態註冊方式,方法名按照標準寫法Java_包名_類名_方法名
*/
extern "C" JNIEXPORT jstring JNICALL Java_com_jianjin33_demo2_MainActivity_stringFromJNI(
JNIEnv *env,
jobject /* this */)
{
std::string hello = "Hello from C++";
return env->NewStringUTF(hello.c_str());
}
// 接下來是動態註冊的方式,需要實現jni.h中的JNI_OnLoad方法
// 方法名可以隨意些
extern "C" JNIEXPORT jstring JNICALL native_stringFromJni2(JNIEnv *env, jclass clazz)
{
return env->NewStringUTF("動態註冊jni函數返回結果");
}
static int registerNativeMethods(JNIEnv* env, const char* className,
JNINativeMethod* gMethods, int numMethods)
{
jclass clazz;
clazz = env->FindClass(className);
if (clazz == NULL) {
return JNI_FALSE;
}
if (env->RegisterNatives(clazz, gMethods, numMethods) < 0) {
return JNI_FALSE;
}
return JNI_TRUE;
}
#define JNIREG_CLASS "com/jianjin33/demo2/MainActivity" // 指定要註冊的類
// JNINativeMethod結構體就是文章開頭介紹的
static JNINativeMethod gMethods[] = {
{ "stringFromJni2", "()Ljava/lang/String;", (void*)native_stringFromJni2}, // 綁定
};
static int registerNatives(JNIEnv* env)
{
if (!registerNativeMethods(env, JNIREG_CLASS, gMethods, sizeof(gMethods) / sizeof(gMethods[0])))
return JNI_FALSE;
return JNI_TRUE;
}
JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM* vm, void* reserved)
{
LOGI("%s","開始走JNI_OnLoad");
JNIEnv* env = NULL;
jint result = -1;
if (vm->GetEnv((void**) &env, JNI_VERSION_1_6) != JNI_OK) {
return -1;
}
assert(env != NULL);
if (!registerNatives(env)) { // 註冊
return -1;
}
result = JNI_VERSION_1_6;
return result;
}
java代碼
static {
System.loadLibrary("native-lib");
}
public native String stringFromJNI(); // 靜態註冊方式
public native String stringFromJNI2(); // 動態註冊方式
靜態註冊:根據函數名來建立Java函數和JNI函數之間的關聯關係,要求JNI層函數的名字必須遵守特定的格式,所以書寫起來比較長,並且,初次調用本地函數時要根據函數名搜索JNI層函數來建立關聯關係,會影響運行效率。
動態註冊:擴展性較好,避免了靜態註冊的不足之處。