JNI開(kāi)發(fā)系列③C語(yǔ)言調(diào)用Java字段與方法

接續(xù)上篇JNI開(kāi)發(fā)系列②.h頭文件分析

前情提要

在前面 舌厨, 我們已經(jīng)熟悉了JNI的開(kāi)發(fā)流程 裙椭, .h頭文件的分析 , 生成頭文件javah命令 , 以及java類(lèi)型在C語(yǔ)言中的表現(xiàn)形式 你雌, 值得注意的是 婿崭, java中的所有引用類(lèi)型都是jobject類(lèi)型 氓栈, native生成的函數(shù) 婿着, 以Java_全類(lèi)名_方法名表示竟宋,包名的._表示 丘侠。

概述

在開(kāi)篇的時(shí)候 蜗字,我們就使用java的native方法調(diào)用過(guò)C函數(shù) 脂新, 返回了一個(gè)String類(lèi)型的字符串 争便, 使用(*Env)->NewStringUTF(Env, "Jni C String");函數(shù) 始花, 我們將字符指針轉(zhuǎn)換成jstring 酷宵, java類(lèi)型的字符串返回給了我們的java層 浇垦。今天我們來(lái)學(xué)習(xí) 荣挨, 使用C語(yǔ)言來(lái)調(diào)用Java的字段與方法 默垄。

part 1 : C 函數(shù)訪問(wèn)java字段

一 口锭, 定義Java 的String類(lèi)型字段與修改字段的native方法

// 使用C語(yǔ)言修改java字段
public String name = "zeno" ;

// C語(yǔ)言修改java String 類(lèi)型字段本地方法
public native void accessJavaStringField() ;

// 調(diào)用
HelloJni jni = new HelloJni() ;
System.out.println("修改前 name 的值:"+jni.name);
//C語(yǔ)言修改java字段本地方法
jni.accessJavaStringField();
System.out.println("修改后 name 的值:"+jni.name);

二 鹃操, 在C語(yǔ)言頭文件中定義native方法的實(shí)現(xiàn)函數(shù) 荆隘, 并實(shí)現(xiàn)

// com.zeno.jni_HelloJNI.h
JNIEXPORT void JNICALL Java_com_zeno_jni_HelloJni_accessJavaStringField
(JNIEnv *, jobject);

// Hello_JNI.c

/*C語(yǔ)言訪問(wèn)java String類(lèi)型字段*/
JNIEXPORT void JNICALL Java_com_zeno_jni_HelloJni_accessJavaStringField
(JNIEnv *env, jobject jobj) {

    // 得到j(luò)class
    jclass jcls = (*env)->GetObjectClass(env, jobj); 

    // 得到字段ID
    jfieldID jfID = (*env)->GetFieldID(env, jcls, "name", "Ljava/lang/String;");

    // 得到字段的值
    jstring jstr = (*env)->GetObjectField(env, jobj, jfID);

    // 將jstring類(lèi)型轉(zhuǎn)換成字符指針
    char* cstr = (*env)->GetStringUTFChars(env, jstr, JNI_FALSE);
    //printf("is vaule:%s\n", cstr);
    // 拼接字符
    char text[30] = "  xiaojiu and ";
    strcat(text, cstr);
    //printf("modify value %s\n", text);

    // 將字符指針轉(zhuǎn)換成jstring類(lèi)型
    jstring new_str = (*env)->NewStringUTF(env, text);

    // 將jstring類(lèi)型的變量 , 設(shè)置到j(luò)ava 字段中
    (*env)->SetObjectField(env, jobj, jfID, new_str);
}

三 乱陡, 輸出

修改前 name 的值:zeno
修改后 name 的值:  xiaojiu and zeno

四 仪壮, 分析

首先來(lái)分析C函數(shù):

JNIEXPORT void JNICALL Java_com_zeno_jni_HelloJni_accessJavaStringField
(JNIEnv *env, jobject jobj)

JNIEXPORT jstring JNICALL Java_com_zeno_jni_HelloJni_getStringFromC
(JNIEnv *Env, jclass jclazz)

我們可以看出兩處不同 爽彤, 一處是返回值類(lèi)型 , 一處是函數(shù)參數(shù)類(lèi)型 往核,返回值類(lèi)型沒(méi)什么可講的 聂儒, 在分析.h頭文件的時(shí)候 衩婚, 已經(jīng)詳細(xì)講述了 效斑。那 缓屠, 這兩個(gè)函數(shù)參數(shù)類(lèi)型jobjectjclass有什么區(qū)別呢 敌完? 這兩個(gè)類(lèi)型表示 滨溉, Java的native函數(shù) 业踏, 是成員方法還是類(lèi)方法 勤家, 成員方法需要對(duì)象.方法名 伐脖, 類(lèi)方法則類(lèi)名.方法名 讼庇, 可以在main方法里面直接使用 近尚。

接下來(lái)是:

// 得到j(luò)class jclass就好比java的.class對(duì)象
jclass jcls = (*env)->GetObjectClass(env, jobj);

為什么要得到j(luò)class呢 ?
因?yàn)?和媳,我們要獲取字段ID 留瞳, 在JNI中 她倘, 獲取java字段與方法都需要簽名硬梁。而簽名是在類(lèi)加載的時(shí)候完成 靶溜, 所以在獲取字段ID的時(shí)候需要傳入jclass 罩息。

// 得到字段ID

jfieldID jfID = (*env)->GetFieldID(env, jcls, "name", "Ljava/lang/String;");

通過(guò)傳入jclass , 字段名稱(chēng) 瓷炮, 字段簽名 娘香, 就可以得到字段ID 烘绽,也可使用GetMethodID函數(shù)得到方法ID 俐填。

為什么傳入了字段名稱(chēng)英融,還需要簽名呢 驶悟?
因?yàn)閖ava支持重載 痕鳍, 一個(gè)方法名稱(chēng)可以有多個(gè)不同實(shí)現(xiàn) , 根據(jù)傳入的參數(shù)不同 恭应,所以C語(yǔ)言調(diào)用函數(shù)為了區(qū)分不同的方法昼榛, 而對(duì)每個(gè)方法做了簽名 胆屿, 而字段則可用來(lái)標(biāo)識(shí)類(lèi)型 (僅個(gè)人理解)非迹。

獲取字段與函數(shù)簽名的方式:

在.class的文件目錄下 憎兽,使用`javap -s -p className`   就可以列舉出 纯命, 所有的字段與方法簽名
// 得到字段的值 亿汞, 類(lèi)比java中的 對(duì)象.字段名得到值 疗我, 這里是字段的ID
jstring jstr = (*env)->GetObjectField(env, jobj, jfID);

// 將jstring類(lèi)型轉(zhuǎn)換成字符指針 
char* cstr = (*env)->GetStringUTFChars(env, jstr, JNI_FALSE); 
//printf("is vaule:%s\n", cstr); 
// 拼接字符 char text[30] = " xiaojiu and "; strcat(text, cstr);
// 將字符指針轉(zhuǎn)換成jstring類(lèi)型 
jstring new_str = (*env)->NewStringUTF(env, text); 

因?yàn)閖ava類(lèi)型與C語(yǔ)言類(lèi)型不是相通的 南捂, 所有需要一個(gè)轉(zhuǎn)換 吴裤, 類(lèi)型的介紹在上一篇已經(jīng)詳細(xì)說(shuō)明 。

// 將jstring類(lèi)型的變量 溺健, 設(shè)置到j(luò)ava 字段中 
// 類(lèi)比java中的 對(duì)象.字段名得到值 麦牺, 這里是字段的ID
(*env)->SetObjectField(env, jobj, jfID, new_str);

畫(huà)龍點(diǎn)睛:
上述中 , 我們?cè)L問(wèn)修改了String類(lèi)型的字段 矿瘦, 也基本上能看出訪問(wèn)字段的基本套路 枕面, 首先得到j(luò)class , 再得到字段ID 愿卒, 繼而得到字段的值 , 進(jìn)行類(lèi)型轉(zhuǎn)換 琼开, 最后將變化的值設(shè)置給Java字段 易结。由此可以推出 , 訪問(wèn)其他類(lèi)型的字段 , 也是這樣的套路 搞动, 只不過(guò)類(lèi)型變了 躏精, 值得注意的是 , java中的引用類(lèi)型是需要進(jìn)行類(lèi)型轉(zhuǎn)換的 鹦肿。

part 2 : C函數(shù)訪問(wèn)Java方法

一 矗烛, 定義Java 方法與調(diào)用方法的native方法

// C語(yǔ)言調(diào)用java方法
private native void accessJavaRandomNumberMethod() ;

// 調(diào)用
jni.accessJavaRandomNumberMethod() ;

二 , 在C語(yǔ)言頭文件中定義native方法的實(shí)現(xiàn)函數(shù) 箩溃, 并實(shí)現(xiàn)


// com.zeno.jni_HelloJNI.h
JNIEXPORT void JNICALL Java_com_zeno_jni_HelloJni_accessJavaRandomNumberMethod
(JNIEnv *, jobject);


// Hello_JNI.c

// 訪問(wèn)java方法
JNIEXPORT void JNICALL Java_com_zeno_jni_HelloJni_accessJavaRandomNumberMethod
(JNIEnv *env, jobject jobj) {

    // 得到j(luò)class
    jclass jclazz = (*env)->GetObjectClass(env, jobj);
    // 得到方法ID
    jmethodID jmtdId = (*env)->GetMethodID(env, jclazz, "getRandomNumber", "(I)I");

    // 調(diào)用方法
    jint jRandomNum = (*env)->CallIntMethod(env, jobj, jmtdId, 10);

    // 打印
    printf("得到j(luò)ava方法的隨機(jī)數(shù):%ld\n", jRandomNum);

}

三 瞭吃, 輸出

得到j(luò)ava方法的隨機(jī)數(shù):6

四 , 分析

不論是字段訪問(wèn)還是方法的調(diào)用 涣旨, 其基本的套路不變 歪架,調(diào)用Java方法與調(diào)用字段不同的是 ,
將得到字段ID改成得到方法ID 霹陡, 得到字段的值改成調(diào)用方法`CallXXX` 和蚪, 通過(guò)調(diào)用調(diào)用Java方法得到方法返回值 。

part 3 : C函數(shù)訪問(wèn)Java字段與方法(靜態(tài))

套路都是一樣的 烹棉, 這里僅給出代碼 攒霹, 不做詳細(xì)分析(本階段全部代碼) 。

/**
 * 
 * @author Zeno
 *
 *  JNI (Java Native Interface) java本地化接口
 *  
 *  Android Framework層與Native層相互通信的基石
 *  
 *
 */
public class HelloJni {
    
    // 使用C語(yǔ)言修改java字段
    public String name = "zeno" ;
    
    // 使用C語(yǔ)言修改java int 類(lèi)型字段
    private int age = 20 ;
    
    public static String flag = "flag1" ;
    

    // 調(diào)用C語(yǔ)言函數(shù)方法
    public static native String getStringFromC() ;
    // 調(diào)用C++語(yǔ)言函數(shù)方法
    public static native String getStringFromCPP() ;
    
    // C語(yǔ)言修改java String 類(lèi)型字段本地方法
    public native void accessJavaStringField() ;
    
    // C語(yǔ)言修改java String static 類(lèi)型字段本地方法
    public native void accessJavaStaticStringField() ;
    
    // C語(yǔ)言修改java int 類(lèi)型字段本地方法
    public native void accessJavaIntField() ;
    
    
    
    // C語(yǔ)言調(diào)用java方法
    private native void accessJavaRandomNumberMethod() ;
    
    // 調(diào)用Java靜態(tài)方法
    private native void accessJavaStaticMethod() ;
    
    // 靜態(tài)native方法訪問(wèn)字段
    private static native void staticAccessJavaField() ;
    
    public static void main(String[] args) {
        
        System.out.println("getStringFormC == "+getStringFromC());
        System.out.println("getStringFormC == "+getStringFromCPP());
        
        HelloJni jni = new HelloJni() ;
        System.out.println("修改前 name 的值:"+jni.name);
        //C語(yǔ)言修改java字段本地方法
        jni.accessJavaStringField();
        System.out.println("修改后 name 的值:"+jni.name);
        
        System.out.println("修改前 flag 的值:"+flag);
        //C語(yǔ)言修改java static 字段本地方法
        jni.accessJavaStaticStringField();
        
        System.out.println("修改后 flag 的值:"+flag);
        
        
        System.out.println("修改前 age 的值:"+jni.age);
        //C語(yǔ)言修改java字段本地方法
        jni.accessJavaIntField();
        
        System.out.println("修改后 age 的值:"+jni.age);
        
        jni.accessJavaRandomNumberMethod() ;
        
        jni.accessJavaStaticMethod() ;
        
        // 靜態(tài)native方法 峦耘,訪問(wèn)java字段
        
        System.out.println("修改前 flag 的值:"+flag);
         staticAccessJavaField();
         
         System.out.println("修改后 flag 的值:"+flag);
    }
    
    static{
        // 加載動(dòng)態(tài)庫(kù)
        System.loadLibrary("Hello_JNI") ;
    }
    
    
    // 調(diào)用java方法
    private int getRandomNumber(int bound) {    
        
        return new Random().nextInt(bound) ;
    }
    
    // 調(diào)用java靜態(tài)方法
    private static String getUUID() {
        return UUID.randomUUID().toString();
    }
}

C實(shí)現(xiàn) 剔蹋, 這里就不貼頭文件了 。
調(diào)用靜態(tài)的Java字段與方法 辅髓, 在C語(yǔ)言中調(diào)用相應(yīng)的static函數(shù) 泣崩, 例如:獲取靜態(tài)字段ID GetStaticFieldID

#define _CRT_SECURE_NO_WARNINGS

#include "com_zeno_jni_HelloJni.h"

#include <string.h>
#include <stdio.h>
#include <stdlib.h>

/*
    C/C++動(dòng)態(tài)庫(kù) 洛口, 在win平臺(tái)下以.dll文件標(biāo)識(shí) 矫付, 在linux下面以.so文件表示
    在Android中 , 以.so文件表示 第焰, 因?yàn)锳ndroid使用的是linux內(nèi)核 买优。

*/



/*
* Class:     com_zeno_jni_HelloJni
* Method:    getStringFormC
* Signature: ()Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_com_zeno_jni_HelloJni_getStringFromC
(JNIEnv *Env, jclass jclazz) {

    return (*Env)->NewStringUTF(Env, "Jni C String");
}

/*C語(yǔ)言訪問(wèn)java String類(lèi)型字段*/
JNIEXPORT void JNICALL Java_com_zeno_jni_HelloJni_accessJavaStringField
(JNIEnv *env, jobject jobj) {

    // 得到j(luò)class , jclass就好比java的.class對(duì)象
    jclass jcls = (*env)->GetObjectClass(env, jobj); 

    // 得到字段ID , 
    jfieldID jfID = (*env)->GetFieldID(env, jcls, "name", "Ljava/lang/String;");

    // 得到字段的值
    jstring jstr = (*env)->GetObjectField(env, jobj, jfID);

    // 將jstring類(lèi)型轉(zhuǎn)換成字符指針
    char* cstr = (*env)->GetStringUTFChars(env, jstr, JNI_FALSE);
    //printf("is vaule:%s\n", cstr);
    // 拼接字符
    char text[30] = "  xiaojiu and ";
    strcat(text, cstr);
    //printf("modify value %s\n", text);

    // 將字符指針轉(zhuǎn)換成jstring類(lèi)型
    jstring new_str = (*env)->NewStringUTF(env, text);

    // 將jstring類(lèi)型的變量 挺举, 設(shè)置到j(luò)ava 字段中
    (*env)->SetObjectField(env, jobj, jfID, new_str);
}

/*C語(yǔ)言訪問(wèn)java int 類(lèi)型字段*/
JNIEXPORT void JNICALL Java_com_zeno_jni_HelloJni_accessJavaIntField
(JNIEnv *env, jobject jobj) {

    // 得到j(luò)class
    jclass jclazz = (*env)->GetObjectClass(env, jobj);

    // 得到字段ID
    jfieldID jfid = (*env)->GetFieldID(env, jclazz, "age", "I");

    // 得到字段值
    jint jAge = (*env)->GetIntField(env, jobj, jfid);

    jAge++;

    (*env)->SetIntField(env, jobj, jfid, jAge);

}

// 訪問(wèn)java方法
JNIEXPORT void JNICALL Java_com_zeno_jni_HelloJni_accessJavaRandomNumberMethod
(JNIEnv *env, jobject jobj) {

    // 得到j(luò)class
    jclass jclazz = (*env)->GetObjectClass(env, jobj);
    // 得到方法ID
    jmethodID jmtdId = (*env)->GetMethodID(env, jclazz, "getRandomNumber", "(I)I");

    // 調(diào)用方法
    jint jRandomNum = (*env)->CallIntMethod(env, jobj, jmtdId, 10);

    // 打印
    printf("得到j(luò)ava方法的隨機(jī)數(shù):%ld\n", jRandomNum);

}


// 訪問(wèn)java靜態(tài)字段
JNIEXPORT void JNICALL Java_com_zeno_jni_HelloJni_accessJavaStaticStringField
(JNIEnv *env, jobject jobj) {

    // 得到j(luò)class
    jclass jclazz = (*env)->GetObjectClass(env, jobj);
    // 得到字段ID
    jfieldID jfid = (*env)->GetStaticFieldID(env, jclazz, "flag", "Ljava/lang/String;");

    // 得到字段的值
    jobject jFLagStr = (*env)->GetStaticObjectField(env, jclazz, jfid);
    
    // 將java字符串轉(zhuǎn)換成C字符指針
    char* cFlagStr = (*env)->GetStringUTFChars(env, jFLagStr, JNI_FALSE);

    //printf("is vaule:%s\n", cFlagStr);

    char newStr[30] = " access static field ";
    strcat(newStr, cFlagStr);

    // 將C字符指針 杀赢, 轉(zhuǎn)換成java字符串
    jstring jNewStr = (*env)->NewStringUTF(env, newStr);

    // 將字符串設(shè)置到j(luò)ava字段上
    (*env)->SetStaticObjectField(env, jclazz, jfid, jNewStr);
}

// 訪問(wèn)java靜態(tài)方法
JNIEXPORT void JNICALL Java_com_zeno_jni_HelloJni_accessJavaStaticMethod
(JNIEnv *env, jobject jobj) {

    // 得到j(luò)class
    jclass jclazz = (*env)->GetObjectClass(env, jobj);

    // 得到靜態(tài)方法ID
    jmethodID mtdid = (*env)->GetStaticMethodID(env, jclazz, "getUUID", "()Ljava/lang/String;");

    // 調(diào)用靜態(tài)方法
    jobject jUUIDStr = (*env)->CallStaticObjectMethod(env, jclazz, mtdid);

    // 將java字符串轉(zhuǎn)換成C字符指針
    char* cUUIDStr = (*env)->GetStringUTFChars(env, jUUIDStr, JNI_FALSE);

    printf("is vaule:%s\n", cUUIDStr);

    // 根據(jù)UUID生成臨時(shí)文件
    char file_path[100] ;
    sprintf(file_path, "e:\\dn\\%s.txt", cUUIDStr);
    printf("is address:%s\n", file_path);

    FILE* fp = fopen(file_path, "w");
    if (fp == NULL) {
        printf("文件創(chuàng)建失敗\n");
    }

    char* content = "落花有意流水無(wú)情";
    // 寫(xiě)入內(nèi)容
    fputs(content, fp);

    // 關(guān)閉流
    fclose(fp);
}



// 靜態(tài)native方法 , 訪問(wèn)java字段
JNIEXPORT void JNICALL Java_com_zeno_jni_HelloJni_staticAccessJavaField
(JNIEnv *env, jclass jclazz) {

    // 得到字段ID
    jfieldID jfid = (*env)->GetStaticFieldID(env, jclazz, "flag", "Ljava/lang/String;");

    // 得到字段的值
    jstring jflag = (*env)->GetStaticObjectField(env, jclazz, jfid);

    // 將java字符串轉(zhuǎn)換成字符指針
    char* cXj = (*env)->GetStringUTFChars(env, jflag, JNI_FALSE);
    printf("is value:%s\n", cflag);
    char newName[100] = "xiaojiu love ";
    char* cNewName = strcat(newName, cflag);

    // 將字符指針轉(zhuǎn)換成java類(lèi)型
    jstring newStr = (*env)->NewStringUTF(env, cNewName);

    // 設(shè)置
    (*env)->SetStaticObjectField(env, jclazz, jfid, newStr);

}

編寫(xiě)套路

C語(yǔ)言訪問(wèn)Java語(yǔ)言的字段與方法 湘纵, 只要理解了一種 脂崔, 其他的都是套路 , 根據(jù)步驟一步一步來(lái)就可以了 梧喷。

步驟一 砌左、 得到jclass 脖咐, 字節(jié)碼對(duì)象 , 如果是static native修飾 汇歹, 則函數(shù)會(huì)以jclass類(lèi)型傳入 屁擅, 非靜態(tài)則需要得到jclass類(lèi)型 。

// 得到j(luò)class 
jclass jclazz = (*env)->GetObjectClass(env, jobj);

步驟二 产弹、得到字段或方法ID , 區(qū)分靜態(tài)字段與對(duì)象字段 派歌, 靜態(tài)字段或方法調(diào)用(*env)->GetStaticFieldID得到靜態(tài)字段ID ,(*env)->GetStaticMethodID得到靜態(tài)方法ID 痰哨, 對(duì)象字段調(diào)用(*env)->GetFieldID得到字段ID硝皂,(*env)->GetMethodID得到方法ID 。 可以得到一個(gè)套路 作谭, 靜態(tài)修飾的 稽物, 則調(diào)用static標(biāo)識(shí)的函數(shù) , 非靜態(tài)的則調(diào)用常規(guī)函數(shù) 折欠。

// 得到字段ID 贝或, 對(duì)象字段
 jfieldID jfid = (*env)->GetFieldID(env, jclazz, "age", "I");

// 得到字段ID , 靜態(tài)字段
jfieldID jfid = (*env)->GetStaticFieldID(env, jclazz, "flag", "Ljava/lang/String;");

步驟三 锐秦、 取得字段的值或調(diào)用方法 , 需要注意的是咪奖, 得到字段的值與調(diào)用方法 , 都有類(lèi)型的區(qū)分 酱床。引用類(lèi)型則使用GetObjectField 羊赵, CallStaticObjectMethod , 其他類(lèi)型 扇谣, 則有對(duì)于的jxxx類(lèi)型對(duì)應(yīng) 昧捷。套路簡(jiǎn)寫(xiě):Get<Type>FieldGetStatic<Type>Field 罐寨, Call<Type>Method 靡挥, CallStatic<Type>Method

// 得到字段的值 
jstring jstr = (*env)->GetObjectField(env, jobj, jfID);

// 得到字段值
 jint jAge = (*env)->GetIntField(env, jobj, jfid);

// 調(diào)用方法 
jint jRandomNum = (*env)->CallIntMethod(env, jobj, jmtdId, 10);

// 調(diào)用靜態(tài)方法
 jobject jUUIDStr = (*env)->CallStaticObjectMethod(env, jclazz, mtdid);

步驟四 鸯绿、 類(lèi)型轉(zhuǎn)換 跋破, 如果是Java引用類(lèi)型 , 則需要進(jìn)行類(lèi)型轉(zhuǎn)換

// 將java字符串轉(zhuǎn)換成字符指針
char* cflag = (*env)->GetStringUTFChars(env, jflag, JNI_FALSE);

結(jié)語(yǔ)

真正的高手 瓶蝴, 不是樂(lè)而學(xué)得的 毒返, 真正的學(xué)習(xí) , 不是輕輕松松的 舷手。高手 拧簸, 需要刻意練習(xí) , 刻意練習(xí)不是重復(fù)相同的動(dòng)作 聚霜, 而是跳出舒適區(qū)熟悉區(qū)域 狡恬, 刻意練習(xí)自己不熟悉感覺(jué)艱難的事情 。感謝動(dòng)腦學(xué)院 蝎宇。

本文由老司機(jī)學(xué)院【動(dòng)腦學(xué)院】特約提供弟劲。

做一家受人尊敬的企業(yè),做一位令人尊敬的老師

參考資料:
Java Native Interface 6.0 Specification

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末姥芥,一起剝皮案震驚了整個(gè)濱河市兔乞,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌凉唐,老刑警劉巖庸追,帶你破解...
    沈念sama閱讀 206,723評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異台囱,居然都是意外死亡淡溯,警方通過(guò)查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,485評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門(mén)簿训,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)咱娶,“玉大人,你說(shuō)我怎么就攤上這事强品”煳辏” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 152,998評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵的榛,是天一觀的道長(zhǎng)琼了。 經(jīng)常有香客問(wèn)我,道長(zhǎng)夫晌,這世上最難降的妖魔是什么雕薪? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 55,323評(píng)論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮晓淀,結(jié)果婚禮上蹦哼,老公的妹妹穿的比我還像新娘。我一直安慰自己要糊,他們只是感情好纲熏,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,355評(píng)論 5 374
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著锄俄,像睡著了一般局劲。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上奶赠,一...
    開(kāi)封第一講書(shū)人閱讀 49,079評(píng)論 1 285
  • 那天鱼填,我揣著相機(jī)與錄音,去河邊找鬼毅戈。 笑死苹丸,一個(gè)胖子當(dāng)著我的面吹牛愤惰,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播赘理,決...
    沈念sama閱讀 38,389評(píng)論 3 400
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼宦言,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了商模?” 一聲冷哼從身側(cè)響起奠旺,我...
    開(kāi)封第一講書(shū)人閱讀 37,019評(píng)論 0 259
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎施流,沒(méi)想到半個(gè)月后响疚,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,519評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡瞪醋,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,971評(píng)論 2 325
  • 正文 我和宋清朗相戀三年忿晕,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片银受。...
    茶點(diǎn)故事閱讀 38,100評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡杏糙,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出蚓土,到底是詐尸還是另有隱情宏侍,我是刑警寧澤,帶...
    沈念sama閱讀 33,738評(píng)論 4 324
  • 正文 年R本政府宣布蜀漆,位于F島的核電站谅河,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏确丢。R本人自食惡果不足惜绷耍,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,293評(píng)論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望鲜侥。 院中可真熱鬧褂始,春花似錦、人聲如沸描函。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,289評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)舀寓。三九已至胆数,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間互墓,已是汗流浹背必尼。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,517評(píng)論 1 262
  • 我被黑心中介騙來(lái)泰國(guó)打工, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留篡撵,地道東北人判莉。 一個(gè)月前我還...
    沈念sama閱讀 45,547評(píng)論 2 354
  • 正文 我出身青樓豆挽,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親券盅。 傳聞我的和親對(duì)象是個(gè)殘疾皇子帮哈,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,834評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容

  • 現(xiàn)在,你知道了如何通過(guò)JNI來(lái)訪問(wèn)JVM中的基本類(lèi)型數(shù)據(jù)和字符串渗饮、數(shù)組這樣的引用類(lèi)型數(shù)據(jù),下一步就是學(xué)習(xí)怎么樣和J...
    738bc070cd74閱讀 870評(píng)論 0 1
  • 1. Java基礎(chǔ)部分 基礎(chǔ)部分的順序:基本語(yǔ)法宿刮,類(lèi)相關(guān)的語(yǔ)法互站,內(nèi)部類(lèi)的語(yǔ)法,繼承相關(guān)的語(yǔ)法僵缺,異常的語(yǔ)法胡桃,線程的語(yǔ)...
    子非魚(yú)_t_閱讀 31,587評(píng)論 18 399
  • 接續(xù)上篇JNI開(kāi)發(fā)系列③C語(yǔ)言調(diào)用Java字段與方法 前情提要 Java調(diào)用C方法很簡(jiǎn)單 , 只需要編寫(xiě)nativ...
    逝我閱讀 2,282評(píng)論 5 6
  • 什么是JNI磕潮? JNI 是java本地開(kāi)發(fā)接口.JNI 是一個(gè)協(xié)議,這個(gè)協(xié)議用來(lái)溝通java代碼和外部的本地代碼(...
    a_tomcat閱讀 2,814評(píng)論 0 54
  • 記得年初的一個(gè)晚上自脯,跟秋同學(xué)聊天之景。兩個(gè)單身青年,談到對(duì)未來(lái)另一半的期待膏潮,秋同學(xué)blabla說(shuō)了一大堆锻狗,我估摸了一下...
    文十言閱讀 296評(píng)論 1 1