Android NDK開(kāi)發(fā)之旅11--JNI--JNI數(shù)據(jù)類型與方法屬性訪問(wèn)

JNI數(shù)據(jù)類型

JNI的數(shù)據(jù)類型包含兩種: 基本類型和引用類型

基本類型

基本類型主要有jboolean, jchar, jint等, 它們和Java中的數(shù)據(jù)類型對(duì)應(yīng)關(guān)系如下表所示:

Java類型 JNI類型 描述
boolean jboolean 無(wú)符號(hào)8位整型
byte byte 無(wú)符號(hào)8位整型
char jchar 無(wú)符號(hào)16位整型
short jshort 有符號(hào)16位整型
int jint 32位整型
long jlong 64位整型
float jfloat 32位浮點(diǎn)型
double jdouble 64位浮點(diǎn)型
void void 無(wú)類型

引用類型(對(duì)象)

JNI中的引用類型主要有類, 對(duì)象和數(shù)組. 它們和Java中的引用類型的對(duì)應(yīng)關(guān)系如下表所示:

Java類型 JNI類型 描述
Object jobject Object類型
Class jclass Class類型
String jstring String類型
Object[] jobjectArray 對(duì)象數(shù)組
boolean[] jbooleanArray boolean數(shù)組
byte[] jbyteArray byte數(shù)組
char[] jcharArray char數(shù)組
short[] jshortArray short數(shù)組
int[] jintArray int數(shù)組
long[] jlongArray long數(shù)組
float[] jfloatArray float數(shù)組
double[] jdoubleArray double數(shù)組
Throwable jthrowable Throwable

native函數(shù)參數(shù)說(shuō)明

每個(gè)native函數(shù),都至少有兩個(gè)參數(shù)(JNIEnv*,jclass或者jobject)啥供。

1)當(dāng)native方法為靜態(tài)方法時(shí):
jclass 代表native方法所屬類的class對(duì)象(JniTest.class)悯恍。

2)當(dāng)native方法為非靜態(tài)方法時(shí):
jobject 代表native方法所屬的對(duì)象。

native函數(shù)的頭文件可以自己寫伙狐。

關(guān)于屬性與方法的簽名

數(shù)據(jù)類型 簽名
boolean Z
byte B
char C
short S
int I
long J
float F
double D
ully-qualified-class Lfully-qualified-class;
type[] [type
method type (arg-types)ret-type
注意:
  • 類描述符開(kāi)頭的 'L' 與結(jié)尾的 ';' 必須要有
  • 數(shù)組描述符,開(kāi)頭的 '[' 必須要有
  • 方法描述符規(guī)則: "(各參數(shù)描述符)返回值描述符",其中參數(shù)描述符間沒(méi)有任何分隔符號(hào)

從上表可以看出, 基本數(shù)據(jù)類型的簽名基本都是單詞的首字母大寫, 但是boolean和long除外因?yàn)锽已經(jīng)被byte占用, 而long也被Java類簽名的占用.

對(duì)象和數(shù)組的簽名稍微復(fù)雜一些.

對(duì)象的簽名就是對(duì)象所屬的類簽名, 比如String對(duì)象, 它的簽名為L(zhǎng)java/lang/String; .

數(shù)組的簽名為[+類型簽名, 例如byte數(shù)組. 其類型為byte, 而byte的簽名為B, 所以byte數(shù)組的簽名就是[B.同理可以得到如下的簽名對(duì)應(yīng)關(guān)系:

char[]      [C
float[]     [F
double[]    [D
long[]      [J
String[]    [Ljava/lang/String;
Object[]    [Ljava/lang/Object;

方法簽名具體方法:
獲取方法的簽名比較麻煩一些涮毫,通過(guò)下面的方法也可以拿到屬性的簽名。
打開(kāi)命令行贷屎,輸入javap罢防,出現(xiàn)以下信息:

javap命令

上述信息告訴我們,通過(guò)以下命令就可以拿到指定類的所有屬性唉侄、方法的簽名了咒吐,很方便有木有?!

javap -s -p 完整類名

我們通過(guò)cd命令渤滞,來(lái)到編譯生成的class字節(jié)碼文件目錄(注意:非src目錄贬墩。 eclipse 編譯生成的class字節(jié)碼文件在bin文件夾中, 而用idea編譯器 編譯生成的class字節(jié)碼文件在out\production下)妄呕,然后輸入命令:

D:\IdeaProjects\jni1\out\production\jni1>javap -s -p com.haocai.jni.JniTest 

得到以下信息:

Compiled from "JniTest.java"
public class com.haocai.jni.JniTest {
  public java.lang.String key;
    descriptor: Ljava/lang/String;
  public static int count;
    descriptor: I
  public com.haocai.jni.JniTest();
    descriptor: ()V

  public static native java.lang.String getStringFromC();
    descriptor: ()Ljava/lang/String;

  public native java.lang.String getString2FromC(int);
    descriptor: (I)Ljava/lang/String;

  public native java.lang.String accessField();
    descriptor: ()Ljava/lang/String;

  public native void accessStaticField();
    descriptor: ()V

  public native void accessMethod();
    descriptor: ()V

  public native void accessStaticMethod();
    descriptor: ()V

  public static void main(java.lang.String[]);
    descriptor: ([Ljava/lang/String;)V

  public int genRandomInt(int);
    descriptor: (I)I

  public static java.lang.String getUUID();
    descriptor: ()Ljava/lang/String;

  static {};
    descriptor: ()V
}
其中陶舞,descriptor:對(duì)應(yīng)的值就是我們需要的簽名了,注意簽名中末尾的分號(hào) ";" 不能省略绪励。

C/C++訪問(wèn)Java的屬性肿孵、方法

在JNI調(diào)用中,肯定會(huì)涉及到本地方法操作Java類中數(shù)據(jù)和方法疏魏。在Java1.0中“原始的”Java到C的綁定中停做,程序員可以直接訪問(wèn)對(duì)象數(shù)據(jù)域。然而大莫,直接方法要求虛擬機(jī)暴露他們的內(nèi)部數(shù)據(jù)布局蛉腌,基于這個(gè)原因,JNI要求程序員通過(guò)特殊的JNI函數(shù)來(lái)獲取和設(shè)置數(shù)據(jù)以及調(diào)用java方法只厘。

有以下幾種情況:

1.訪問(wèn)Java類的非靜態(tài)屬性烙丛。
2.訪問(wèn)Java類的靜態(tài)屬性。
3.訪問(wèn)Java類的非靜態(tài)方法羔味。
4.訪問(wèn)Java類的靜態(tài)方法河咽。
5.間接訪問(wèn)Java類的父類的方法。
6.訪問(wèn)Java類的構(gòu)造方法赋元。

一忘蟹、訪問(wèn)Java的非靜態(tài)屬性

Java聲明如下:

 public String name = "kpioneer";

//訪問(wèn)非靜態(tài)屬性name,修改它的值 
//accessField 自定義的一個(gè)方法
public native void accessField();

C代碼如下:

//把java中的變量name中值kpioneer 變?yōu)閗pioneer Goodman
JNIEXPORT jstring JNICALL Java_com_haocai_jni_JniTest_accessField
(JNIEnv *env, jobject jobject) {
    //Jclass 
    //jobj是t對(duì)象
    jclass cls = (*env)->GetObjectClass(env, jobject);
    //jfieldID
    //屬性名稱搁凸,屬性簽名
    jfieldID fid = (*env)->GetFieldID(env, cls, "name", "Ljava/lang/String;");


    //類似于反射
    //拿到j(luò)niTest(jobject) 中name的值
    /*
    Get<Type>Field:
    GetFloatField
    GetIntField
    GetLongField
    ...
    */
    jstring jstr = (*env)->GetObjectField(env, jobject, fid);
    printf("jstr:%#x\n", &jstr);
    //printf("jstr:%#x\n", &jstr);
    //jstring -> C 字符串

    boolean isCopy =NULL;
    //函數(shù)內(nèi)部復(fù)制了媚值,isCopy 為JNI_TRUE,沒(méi)有復(fù)制JNI_FALSE
    char *c_str = (*env)->GetStringUTFChars(env, jstr, &isCopy );
    //意義:isCopy為JNI_FALSE,c_str和jstr都指向同一個(gè)字符串,不能修改java字符串

    char text[20] = " Goodman";
    strcat(c_str, text);//拼接函數(shù)

    //再把C字符串 ->jstring
    jstring new_str = (*env)->NewStringUTF(env, c_str);
    printf("jstr:%#x\n", &new_str);
    //修改name
    /*
    Set<Type>Field:
    SetFloatField
    SetIntField
    SetLongField
    ...
    */
    (*env)->SetObjectField(env, jobject, fid, new_str);

    //最后釋放資源坪仇,通知垃圾回收器來(lái)回收
    //良好的習(xí)慣就是杂腰,每次GetStringUTFChars,結(jié)束的時(shí)候都有一個(gè)ReleaseStringUTFChars與之呼應(yīng)
    (*env)->ReleaseStringUTFChars(env, jstr, c_str);
    return new_str;
}

最后在Java中測(cè)試:

public static void main(String[] args) {
        JniTest jniTest = new JniTest();
        System.out.println("name修改前:"+jniTest.name);
        jniTest.accessField();
        System.out.println("name修改后:"+jniTest.name);
}

結(jié)果輸出:
name修改前:kpioneer
name修改后:kpioneer Goodman
jstr:0x27cf238  //調(diào)用的C也打印輸出
jstr:0x27cf2a8  

二椅文、訪問(wèn)Java的靜態(tài)屬性

Java聲明如下:

public static int count = 9;
public native void accessStaticField();

C代碼如下:

//訪問(wèn)靜態(tài)屬性
JNIEXPORT void JNICALL Java_com_haocai_jni_JniTest_accessStaticField
(JNIEnv *env, jobject jobj) {
    //jclass
    jclass cls = (*env)->GetObjectClass(env, jobj);
    //jfieldID
    jfieldID fid =(*env)->GetStaticFieldID(env, cls, "count", "I");
    //GetStatic<Type>Field
    jint count = (*env)->GetStaticIntField(env, cls, fid);
    count++;
    //修改
    //SetStatic<Type>Field
    (*env)->SetStaticIntField(env, cls, fid, count);
}

最后在Java中測(cè)試:

public static void main(String[] args) {
    JniTest jniTest= new JniTest();
    System.out.println("count修改前:"+count);
    jniTest.accessStaticField();
    System.out.println("count修改后:"+count);
}

結(jié)果輸出:
count修改前:9
count修改后:10

三、訪問(wèn)Java的非靜態(tài)方法

Java聲明如下:

    //產(chǎn)生指定范圍的隨機(jī)數(shù)
    public int genRandomInt(int max){
        System.out.println("genRandomInt 執(zhí)行了..");
        return new Random().nextInt(max);
    }

C代碼如下:

JNIEXPORT void JNICALL Java_com_haocai_jni_JniTest_accessMethod
(JNIEnv *env, jobject jobj) {

    //Jclass
    jclass cls = (*env)->GetObjectClass(env, jobj);
    //JmethodID
    jfieldID mFid = (*env)->GetMethodID(env, cls, "genRandomInt", "(I)I");
    //調(diào)用
    //Call<Type>Method
    jint random = (*env)->CallIntMethod(env, jobj, mFid, 200);
    printf("random num:%ld",random);

}

最后在Java中測(cè)試:

public static void main(String[] args) {
    JniTest jniTest= new JniTest();
    jniTest.accessMethod();
}
結(jié)果輸出:
genRandomInt 執(zhí)行了..

random num:109

四惜颇、訪問(wèn)Java的靜態(tài)方法

Java聲明如下:

    public static  String getUUID(){
      return  UUID.randomUUID().toString();
    }

C代碼如下:

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

    //Jclass
    jclass cls = (*env)->GetObjectClass(env, jobj);
    //JmethodID
    jfieldID mFid = (*env)->GetStaticMethodID(env, cls, "getUUID", "()Ljava/lang/String;");

    //調(diào)用
    //CallStatic<Type>Method
    jstring uuid = (*env)->CallStaticObjectMethod(env, jobj, mFid);
    
    //隨機(jī)文件名稱 uuid.txt
    //jstring -> char*
    //isCopy JNI_FALSE,代表java和c操作的是同一個(gè)字符串
    char *uuid_str = (*env)->GetStringUTFChars(env, uuid, NULL);
    //拼接
    char filename[100];
    sprintf(filename, "D://%s.txt", uuid_str);
    FILE *fp = fopen(filename, "w");
    fputs("i love kpioneer", fp);
    fclose(fp);


}

最后在Java中測(cè)試:

public static void main(String[] args) {
        JniTest jniTest = new JniTest();

        jniTest.accessStaticMethod();.
}
最終在D盤目錄下生成名為2fbf3e41-741b-4899-8e4e-a6a80a23a0b2(UUID隨機(jī)生成) 的txt文件

五皆刺、訪問(wèn)Java類的構(gòu)造方法

Java聲明如下:

    public native long accessConstructor();

C代碼如下:

//訪問(wèn)Java類的構(gòu)造方法
//使用java.util.Date產(chǎn)生一個(gè)當(dāng)前的事件戳
JNIEXPORT jlong  JNICALL Java_com_haocai_jni_JniTest_accesssConstructor
(JNIEnv *env, jobject jobj) {

    jclass cls = (*env)->FindClass(env, "java/util/Date");
    //jmethodID
    jmethodID  constructor_mid= (*env)->GetMethodID(env, cls,"<init>","()V");
    //實(shí)例化一個(gè)Date對(duì)象(可以在constructor_mid后加參)
    jobject date_obj =  (*env)->NewObject(env, cls, constructor_mid);
    //調(diào)用getTime方法
    jmethodID mid = (*env)->GetMethodID(env, cls, "getTime", "()J");
    jlong time = (*env)->CallLongMethod(env, date_obj, mid);

    printf("time:%lld\n",time);

    return time;

}

最后在Java中測(cè)試:

public static void main(String[] args) {

        JniTest test = new JniTest();
        //直接在Java中構(gòu)造Date然后調(diào)用getTime
        Date date = new Date();
        System.out.println(date.getTime());
        //通過(guò)C語(yǔ)音構(gòu)造Date然后調(diào)用getTime
        long time = jniTest.accessConstructor();
        System.out.println(time);
}


結(jié)果輸出:
1509688828013
1509688828013

time:1509688828013

六、間接訪問(wèn)Java類的父類的方法

Java代碼如下:
父類:

public class Human {
    public void sayHi(){
        System.out.println("人類打招乎(父類)");
    }
}

子類:

public class Man extends Human {
    @Override
    public void sayHi() {
        System.out.println("男人打招乎");
    }
}

在TestJni類中有Human方法聲明:

    public Human human = new Man();

    public native void accessNonvirtualMethod();

如果是直接使用human .sayHi()的話凌摄,其實(shí)訪問(wèn)的是子類Man的方法
但是通過(guò)底層C的方式可以間接訪問(wèn)到父類Human的方法羡蛾,跳過(guò)子類的實(shí)現(xiàn),甚至你可以直接哪個(gè)父類(如果父類有多個(gè)的話)锨亏,這是Java做不到的痴怨。

下面是C代碼實(shí)現(xiàn)忙干,無(wú)非就是屬性和方法的訪問(wèn):

//調(diào)用父類的方法
JNIEXPORT void JNICALL Java_com_haocai_jni_JniTest_accessNonvirtualMethod
(JNIEnv *env, jobject jobj) {

    jclass cls = (*env)->GetObjectClass(env, jobj);

    //獲取man屬性(對(duì)象)
    jfieldID fid = (*env)->GetFieldID(env, cls, "human", "Lcom/haocai/jni/Human;");
    //獲取
    jobject human_obj = (*env)->GetObjectField(env, jobj, fid);

    //執(zhí)行sayHi方法
    jclass human_cls = (*env)->FindClass(env, "com/haocai/jni/Human");
    jmethodID mid = (*env)->GetMethodID(env, human_cls, "sayHi", "()V");
    
    //執(zhí)行Java相關(guān)的子類方法
    (*env)->CallObjectMethod(env, human_obj, mid);

    //執(zhí)行Java相關(guān)的父類方法
    (*env)->CallNonvirtualObjectMethod(env, human_obj, human_cls, mid);

}

1.當(dāng)有這個(gè)類的對(duì)象的時(shí)候,使用(env)->GetObjectClass()浪藻,相當(dāng)于Java中的test.getClass()
2.當(dāng)有沒(méi)有這個(gè)類的對(duì)象的時(shí)候捐迫,(
env)->FindClass(),相當(dāng)于Java中的Class.forName("com.test.TestJni")
這里直接使用CallVoidMethod爱葵,雖然傳進(jìn)去的是父類的Method ID施戴,但是訪問(wèn)的讓然是子類的實(shí)現(xiàn)。

最后萌丈,通過(guò)CallNonvirtualVoidMethod赞哗,訪問(wèn)不覆蓋的父類方法(C++使用virtual關(guān)鍵字來(lái)覆蓋父類的實(shí)現(xiàn)),當(dāng)然你也可以指定哪個(gè)父類(如果有多個(gè)父類的話)辆雾。

最后在Java中測(cè)試:

    public static void main(String[] args) {
        JniTest jniTest = new JniTest();
        jniTest.human.sayHi();
        jniTest.accessNonvirtualMethod();

    }

結(jié)果輸出:
男人打招乎
男人打招乎  
人類打招乎(父類) 

實(shí)際案例---用JNI方法和屬性訪問(wèn)解決中文編碼亂碼問(wèn)題

中文亂碼

    char *cOutStr = "李四";
    string jstr = (*env)->NewStringUTF(env, cOutStr);
    return jstr; 直接返回會(huì)有中文亂碼問(wèn)題
原因分析肪笋,調(diào)用NewStringUTF的時(shí)候,產(chǎn)生的是UTF-16的字符串度迂,但是我們需要的時(shí)候UTF-8字符串涂乌。
如果使用C語(yǔ)言方法解決中文編碼問(wèn)題,代碼行數(shù)多(幾百行+)英岭,且容易產(chǎn)生問(wèn)題湾盒。所以直接通過(guò)Java 中的String(byte bytes[],String charsetName)構(gòu)造方法來(lái)進(jìn)行字符集變換,解決該問(wèn)題诅妹。

Java聲明如下:

  public native String chineseChars(String str);

C代碼如下:

JNIEXPORT jstring JNICALL Java_com_haocai_jni_JniTest_chineseChars
(JNIEnv *env, jobject jobj,jstring in) {

//輸出
    char *cStr = (*env)->GetStringUTFChars(env, in, JNI_FALSE);
    printf("C %s\n", cStr);


    //c -> jstring
    char *cOutStr = "李四";
    //jstring jstr = (*env)->NewStringUTF(env, cOutStr);
    //return jstr; 直接返回會(huì)有中文亂碼問(wèn)題

    //解決中文亂碼問(wèn)題
    //執(zhí)行java 中String(byte bytes[],String charsetName);
    //1.jmethodID
    //2.byte數(shù)組
    //3.字符編碼

    jstring str_cls = (*env)->FindClass(env, "java/lang/String");
    //構(gòu)造方法用<init>
    jmethodID construvtor_mid =  (*env)->GetMethodID(env, str_cls, "<init>", "([BLjava/lang/String;)V");

    //jbyte-> char
    //jbyteArray -> char[]
    jbyteArray bytes = (*env)->NewByteArray(env, strlen(cOutStr));
    //byte數(shù)組賦值
    //從0到strlen(cOutStr)罚勾,從頭到尾
    (*env)->SetByteArrayRegion(env,bytes,0,strlen(cOutStr), cOutStr);

    //字符編碼jstring
    jstring charsetName = (*env)->NewStringUTF(env, "GB2312");

    //調(diào)用構(gòu)造函數(shù),返回編碼之后的jstring


    return (*env)->NewObject(env,str_cls, construvtor_mid,bytes, charsetName);

}

最后在Java中測(cè)試:

    public static void main(String[] args) {
       JniTest jniTest = new JniTest();
       String outStr = jniTest.chineseChars("張三");
       System.out.println("中文輸出:"+outStr);
    }

結(jié)果輸出:
中文輸出:李四

C 張三

總結(jié)

  • 1.C/C++完成的功能并不是所有代碼一定要C/C++語(yǔ)句寫吭狡,有時(shí)候C/C++可以調(diào)用現(xiàn)成的Java方法或?qū)傩越鉀Q問(wèn)題尖殃,能起到事半功倍的作用。
  • 2.屬性划煮、方法的訪問(wèn)的使用是和Java的反射相類似送丰。

特別感謝:
動(dòng)腦學(xué)院Jason

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市弛秋,隨后出現(xiàn)的幾起案子器躏,更是在濱河造成了極大的恐慌,老刑警劉巖蟹略,帶你破解...
    沈念sama閱讀 216,372評(píng)論 6 498
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件登失,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡挖炬,警方通過(guò)查閱死者的電腦和手機(jī)揽浙,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 92,368評(píng)論 3 392
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái),“玉大人馅巷,你說(shuō)我怎么就攤上這事膛虫。” “怎么了钓猬?”我有些...
    開(kāi)封第一講書人閱讀 162,415評(píng)論 0 353
  • 文/不壞的土叔 我叫張陵稍刀,是天一觀的道長(zhǎng)。 經(jīng)常有香客問(wèn)我逗噩,道長(zhǎng)掉丽,這世上最難降的妖魔是什么? 我笑而不...
    開(kāi)封第一講書人閱讀 58,157評(píng)論 1 292
  • 正文 為了忘掉前任异雁,我火速辦了婚禮捶障,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘纲刀。我一直安慰自己项炼,他們只是感情好,可當(dāng)我...
    茶點(diǎn)故事閱讀 67,171評(píng)論 6 388
  • 文/花漫 我一把揭開(kāi)白布示绊。 她就那樣靜靜地躺著锭部,像睡著了一般。 火紅的嫁衣襯著肌膚如雪面褐。 梳的紋絲不亂的頭發(fā)上拌禾,一...
    開(kāi)封第一講書人閱讀 51,125評(píng)論 1 297
  • 那天,我揣著相機(jī)與錄音展哭,去河邊找鬼湃窍。 笑死,一個(gè)胖子當(dāng)著我的面吹牛匪傍,可吹牛的內(nèi)容都是我干的您市。 我是一名探鬼主播,決...
    沈念sama閱讀 40,028評(píng)論 3 417
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼役衡,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼茵休!你這毒婦竟也來(lái)了?” 一聲冷哼從身側(cè)響起手蝎,我...
    開(kāi)封第一講書人閱讀 38,887評(píng)論 0 274
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤榕莺,失蹤者是張志新(化名)和其女友劉穎,沒(méi)想到半個(gè)月后柑船,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體帽撑,經(jīng)...
    沈念sama閱讀 45,310評(píng)論 1 310
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 37,533評(píng)論 2 332
  • 正文 我和宋清朗相戀三年鞍时,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點(diǎn)故事閱讀 39,690評(píng)論 1 348
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡逆巍,死狀恐怖及塘,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情锐极,我是刑警寧澤笙僚,帶...
    沈念sama閱讀 35,411評(píng)論 5 343
  • 正文 年R本政府宣布,位于F島的核電站灵再,受9級(jí)特大地震影響肋层,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜翎迁,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 41,004評(píng)論 3 325
  • 文/蒙蒙 一栋猖、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧汪榔,春花似錦蒲拉、人聲如沸。這莊子的主人今日做“春日...
    開(kāi)封第一講書人閱讀 31,659評(píng)論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至士聪,卻和暖如春锦援,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背剥悟。 一陣腳步聲響...
    開(kāi)封第一講書人閱讀 32,812評(píng)論 1 268
  • 我被黑心中介騙來(lái)泰國(guó)打工灵寺, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人懦胞。 一個(gè)月前我還...
    沈念sama閱讀 47,693評(píng)論 2 368
  • 正文 我出身青樓替久,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親躏尉。 傳聞我的和親對(duì)象是個(gè)殘疾皇子蚯根,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 44,577評(píng)論 2 353

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