头条:JNI知识点总结
博客园 2023-03-29 06:46:25

JNI开发中静态和动态注册

JNI(Java Native Interface)是Java平台提供的一种机制,用于在Java程序中调用本地代码(例如C/C++代码)。 JNI中涉及两种类型的方法注册:静态注册和动态注册。


(资料图)

静态注册是指将本地方法的名称和实现直接映射到Java类的静态方法。这可以通过在C/C++代码中使用特定命名模式(例如Java_com_example_MyClass_myMethod)来实现。然后,可以使用System.loadLibrary()方法在Java代码中加载本地库,并直接调用本地方法。

动态注册是指在Java代码中使用JNI提供的一组API动态地注册本地方法。使用动态注册,可以在运行时加载本地库,并将方法名称和实现与Java类的实例方法绑定。这样,在Java代码中创建类实例时,可以直接调用本地方法。

静态注册通常比动态注册更快,因为它可以避免在Java代码中使用JNI API注册本地方法。但是,它也有一些缺点。例如,由于本地方法的名称必须遵循特定的命名约定,因此它可能不太灵活。此外,如果在运行时加载本地库时发生错误,将无法捕获它。

动态注册通常更灵活,因为它可以在运行时动态加载本地库并动态注册方法。此外,它也可以避免命名约定的限制。但是,它也比静态注册慢,因为它涉及在Java代码中使用JNI API注册本地方法。

假设有以下Java类:

public class MyNativeClass {    static {        System.loadLibrary("MyNativeLibrary");    }        public static native void myStaticMethod();        public native void myInstanceMethod();}

此Java类具有两种本地方法:静态方法myStaticMethod和实例方法myInstanceMethod。这两个方法的实现将在本地库"MyNativeLibrary"中定义。

下面是静态注册和动态注册的具体示例:

静态注册

假设我们使用以下C/C++代码实现本地方法:

JNIEXPORT void JNICALL Java_com_example_MyNativeClass_myStaticMethod(JNIEnv *env, jclass clazz) {    // 实现静态方法} JNIEXPORT void JNICALL Java_com_example_MyNativeClass_myInstanceMethod(JNIEnv *env, jobject obj) {    // 实现实例方法}

在静态注册中,必须使用特定的命名约定将本地方法名称映射到Java类的静态方法。在本例中,我们使用的是"Java_com_example_MyNativeClass_myStaticMethod"和"Java_com_example_MyNativeClass_myInstanceMethod"。这些方法必须在本地库中实现。

然后,在Java代码中,我们可以直接调用静态方法myStaticMethod(),如下所示:

MyNativeClass.myStaticMethod();

动态注册

在动态注册中,我们必须在Java代码中使用JNI API动态注册本地方法。以下是动态注册的示例代码:

JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm, void *reserved) {    JNIEnv *env;    jclass cls;    JNINativeMethod methods[] = {        {"myInstanceMethod", "()V", (void*) myInstanceMethod}    };    if ((*vm)->GetEnv(vm, (void **)&env, JNI_VERSION_1_6) != JNI_OK) {        return JNI_ERR;    }    cls = (*env)->FindClass(env, "com/example/MyNativeClass");    if (cls == NULL) {        return JNI_ERR;    }    if ((*env)->RegisterNatives(env, cls, methods, 1) < 0) {        return JNI_ERR;    }    return JNI_VERSION_1_6;}JNIEXPORT void JNICALL myInstanceMethod(JNIEnv *env, jobject obj) {    // 实现实例方法}

首先,我们实现了JNI_OnLoad()方法,在其中使用JNI API动态注册本地方法。在此示例中,我们只注册了一个实例方法myInstanceMethod()。

然后,在Java代码中,我们可以创建MyNativeClass的实例并调用本地方法myInstanceMethod(),如下所示:

MyNativeClass obj = new MyNativeClass();obj.myInstanceMethod();

总体而言,静态注册和动态注册都可以实现在Java代码中调用本地方法。静态注册更简单,但有一些限制。动态注册更灵活,但需要在Java代码中使用JNI API注册本地方法。

jni的动态注册能解决什么问题

动态注册是JNI的一个功能,它允许我们在C/C++代码中动态地将本地方法与Java类绑定在一起。相对于静态注册,动态注册具有以下优势:

  1. 灵活性更高:使用动态注册,我们可以在程序运行时动态地添加或删除本地方法,而不需要重新编译整个程序。

  2. 可移植性更好:使用静态注册时,我们需要手动编写Java本地接口(JNI)代码,并将其与C/C++代码一起编译成共享库。这会导致库在不同的操作系统和编译器上表现不一致。而使用动态注册,我们只需要将C/C++代码编译成共享库,然后在Java代码中加载该库即可。

  3. 减少代码量:使用静态注册时,我们需要为每个本地方法编写一个Java本地接口(JNI)代码。而使用动态注册,我们可以使用同一个JNI接口方法来处理多个本地方法,从而减少代码量。

jni中方法签名有哪些。怎么选用

在JNI中,方法签名是指用来标识一个方法的唯一字符串,它包括了方法的名称、返回类型和参数列表。方法签名的格式为:(参数类型1, 参数类型2, ... )返回类型,其中参数类型和返回类型都使用Java的类型描述符来表示。

下面是一些常见的Java类型描述符:

例如,java.lang.String的类型描述符为Ljava/lang/String;int[]的类型描述符为[I

在JNI中,有几种常见的方法签名格式,如下:

在选择方法签名时,需要注意以下几点:

通常情况下,可以通过在Java代码中使用javap命令来获取方法的签名,然后在JNI代码中使用对应的签名来实现方法的调用。

使用javap命令

在Java中,可以使用javap命令来查看一个类的方法签名。具体步骤如下:

  1. 在命令行中打开终端或命令提示符。

  2. 切换到包含要查看方法签名的类的目录。

  3. 输入以下命令:

    javap -s 

    其中,是要查看方法签名的类的名称,不包括.class后缀名。

    例如,如果要查看MyClass类的方法签名,可以输入以下命令:

    javap -s MyClass
  4. 然后会输出MyClass类的所有方法及其签名。

    例如:

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

    其中,descriptor后面的字符串就是方法的签名。

注意,在使用javap命令时,需要确保编译器已经编译了该类,并且该类的.class文件已经存在。如果该类还没有被编译,可以先使用javac命令进行编译。

另外,如果要查看一个类的所有继承方法和接口方法的签名,可以在javap命令中加上-s选项。

JNI和java通讯的原理是什么

JNI(Java Native Interface)是Java提供的一种与本地代码交互的机制。它提供了一组标准的接口和规范,使得Java应用程序可以调用本地库中的函数,并且本地库中的函数也可以调用Java应用程序中的函数。JNI的原理可以简单地概括为以下三个步骤:

  1. Java应用程序通过JNI调用本地库中的函数。在调用之前,Java应用程序需要使用System.loadLibrary()System.load()方法加载本地库。然后,Java应用程序通过JNI提供的接口将参数传递给本地库中的函数,并且将本地库中函数的返回值传递回Java应用程序。

  2. 本地库中的函数接收到Java应用程序传递的参数后,通过JNI提供的接口将参数转换为本地代码可以处理的格式,并且调用本地代码中的函数进行处理。

  3. 本地代码中的函数处理完毕后,将结果返回给本地库中的函数。本地库中的函数将结果转换为Java应用程序可以处理的格式,并且将结果返回给Java应用程序。

总体来说,JNI的原理就是通过提供一组标准的接口和规范,使得Java应用程序可以调用本地库中的函数,并且本地库中的函数也可以调用Java应用程序中的函数,从而实现Java和本地代码之间的交互。

jni中本地引用和全局引用

JNI(Java Native Interface)中有两种引用类型:本地引用(local reference)和全局引用(global reference)。本地引用和全局引用的主要区别在于它们的生命周期和作用域范围。

本地引用是指在本地方法中创建的引用。它们只在本地方法的执行期间有效,并且不能被跨越多个本地方法调用使用。当本地方法返回时,所有本地引用都会自动失效,并且对应的内存资源也会被回收。如果在本地方法中创建的本地引用不及时释放,就会导致内存泄漏。

全局引用是指可以在Java虚拟机的整个生命周期中使用的引用。它们是通过调用JNI提供的函数NewGlobalRef()来创建的。全局引用可以被多个本地方法使用,并且在整个Java虚拟机生命周期内都有效。当不再需要全局引用时,可以通过调用JNI提供的函数DeleteGlobalRef()来释放对应的内存资源。

一般来说,当需要在多个本地方法中使用同一个对象时,可以将其转换为全局引用。同时,在创建本地引用时,应该尽可能地减少其数量,以避免内存泄漏的风险。在使用完本地引用后,应该及时将其释放掉,以释放对应的内存资源。

举个实例

假设有一个Java类MyClass,其中有一个本地方法nativeMethod()。在该方法中,需要使用一个本地引用来引用一个Java对象。同时,由于该对象需要在多个本地方法中使用,因此需要将其转换为全局引用。

java

public class MyClass {    private Object obj;    public native void nativeMethod();    public void setObj(Object obj) {        this.obj = obj;    }    public Object getObj() {        return obj;    }}

在实现nativeMethod()方法的本地代码中,需要使用一个本地引用来引用MyClass对象的obj属性,并且将其转换为全局引用。可以使用以下代码来实现:

c

JNIEXPORT void JNICALL Java_MyClass_nativeMethod(JNIEnv *env, jobject obj) {    // 获取MyClass对象的obj属性    jfieldID fid = (*env)->GetFieldID(env, (*env)->GetObjectClass(env, obj), "obj", "Ljava/lang/Object;");    jobject localRef = (*env)->GetObjectField(env, obj, fid);    // 将本地引用转换为全局引用    jobject globalRef = (*env)->NewGlobalRef(env, localRef);    // 在这里使用全局引用    // 释放全局引用    (*env)->DeleteGlobalRef(env, globalRef);}

在以上代码中,GetObjectClass()函数用于获取MyClass对象的类引用,GetFieldID()函数用于获取obj属性的ID,GetObjectField()函数用于获取obj属性的值,并将其存储在本地引用localRef中。接下来,可以使用NewGlobalRef()函数将本地引用转换为全局引用,并在代码中使用它。最后,通过DeleteGlobalRef()函数释放全局引用的内存资源。

JNI和JNA的区别是什么JNI(Java Native Interface)和JNA(Java Native Access)都是Java程序与本地代码进行交互的技术。

JNI是Java平台提供的一种机制,它可以使Java程序调用C/C++等本地语言编写的代码,并且可以将Java对象传递到本地代码中。JNI需要开发者手动编写一些本地代码,并且需要进行编译和链接。

JNA是一个开源项目,它提供了一种更为简单的方式,使Java程序可以直接访问本地代码。JNA通过Java反射机制实现本地函数的调用,开发者不需要编写任何本地代码,只需要定义本地函数的接口并提供本地库的名称即可。JNA还支持结构体、指针等复杂类型的传递,并且可以自动进行内存管理。

因此,JNI相对而言更加灵活,可以进行更细粒度的控制,但需要更多的开发工作;而JNA则更为简单,开发效率更高,但可能会牺牲一些灵活性和性能。选择何种技术应该根据具体的需求和场景来决定。

举一个JNA实现实例以下是一个使用JNA实现本地函数调用的简单示例:

假设有一个本地库libmymath.so,其中定义了一个函数add,用于计算两个整数的和。

创建Java接口,定义本地函数的接口。

import com.sun.jna.Library;import com.sun.jna.Native;public interface MyMath extends Library {    MyMath INSTANCE = (MyMath) Native.load("mymath", MyMath.class);    int add(int a, int b);}

加载本地库,获取接口实例。

MyMath myMath = MyMath.INSTANCE;

调用本地函数。

int result = myMath.add(1, 2);

在这个示例中,我们使用JNA加载了本地库mymath,并定义了一个接口MyMath,其中add函数的参数和返回值类型与本地库中的函数保持一致。在Java代码中,我们可以通过MyMath.INSTANCE获取接口实例,并直接调用add函数来进行本地函数调用。

JNA不是Android官方的

JNA不是Android官方实现的技术,它是一个独立的开源项目。在Android开发中,通常使用的是Android NDK(Native Development Kit)提供的JNI技术来实现Java和本地代码的交互。NDK是Android官方提供的工具集,可以帮助开发者将本地代码集成到Android应用中。

虽然JNA在Android开发中并不常用,但是在其他平台(如Windows、Linux等)上,JNA广泛应用于Java和本地代码的交互。JNA提供了一种更为简单和便捷的方式来进行本地函数调用,相对于JNI更加容易上手和使用,因此得到了不少开发者的青睐。

如何快速生成native方法

可以通过Java SE提供的javah工具快速生成native方法。

javah命令可以根据Java类的字节码文件,生成对应的C/C++头文件,以便我们在本地代码中实现native方法。具体步骤如下:

  1. 编写Java类,在其中定义native方法。
public class MyClass {    public native void nativeMethod();}
  1. 在命令行中切换到Java类所在目录下,使用javac命令编译Java类。
javac MyClass.java
  1. 使用javah命令生成C/C++头文件。
javah MyClass

执行上述命令后,会在当前目录下生成一个名为MyClass.h的头文件,其中包含了Java类中定义的native方法的函数原型。

/* DO NOT EDIT THIS FILE - it is machine generated */#include /* Header for class MyClass */#ifndef _Included_MyClass#define _Included_MyClass#ifdef __cplusplusextern "C" {#endif/* * Class:     MyClass * Method:    nativeMethod * Signature: ()V */JNIEXPORT void JNICALL Java_MyClass_nativeMethod  (JNIEnv *, jobject);#ifdef __cplusplus}#endif#endif
  1. 在本地代码中实现native方法。

在生成的头文件中,可以找到对应native方法的函数原型。我们可以根据函数原型在本地代码中实现native方法,并使用System.loadLibrary加载对应的本地库。

例如,在C/C++代码中实现nativeMethod函数的示例代码如下:

#include "MyClass.h"JNIEXPORT void JNICALL Java_MyClass_nativeMethod(JNIEnv *env, jobject obj) {    // 实现native方法的代码}

通过以上步骤,我们就可以在Java类中使用定义的native方法,并在本地代码中实现native方法。

头条:JNI知识点总结

2023-03-29 06:46:25

2023年03月29日贵州遵义疫情今日最新情况及遵义疫情防控最新通告今天-焦点速递

2023-03-29 02:51:35

中国南方航空股份(01055)公布2022年业绩 归属于上市公司股东的净亏损约326.82亿元 同比增长1.7倍 天天消息

2023-03-28 23:07:05

美教授:美国若禁TikTok将成“执法噩梦” 是利用仇外心理的表演 世界观速讯

2023-03-28 21:58:47

焦点简讯:TECHSTARACQ-Z(07855)发布年度业绩,亏损7210万港元

2023-03-28 20:17:18

40秒了解:哪些纳税人无需办理个人所得税年度汇算?_全球速看

2023-03-28 18:59:48

当前时讯:下修业绩预告 神开股份2022年最高预亏3000万元

2023-03-28 17:56:45

财报2023|巨子生物收入同增超5成:直销改革带动销售费用翻倍

2023-03-28 17:05:30

【环球快播报】两对情侣的群名(2019年12月14日星座运势)

2023-03-28 16:28:07

沪金期货主力合约日内资金流出超8亿元

2023-03-28 15:48:32

天坛元宇宙发布会举行,启动数字空间“灵境天坛”升级游览体验

2023-03-28 14:18:15

唤醒我歌曲_想念式 苏醒演唱歌曲_当前热门

2023-03-28 13:04:20

甘肃崇信:开往春天的列车-环球热资讯

2023-03-28 11:18:24

确保创文工作全覆盖无死角

2023-03-28 10:24:23

每日观察!金宝:3.28黄金大阴延续走循序,日内1946上买入

2023-03-28 09:26:53

首批2只主板注册制新股中签率出炉 另有8只申购在即 全球最新

2023-03-28 07:53:57

美国田纳西州一学校发生大规模枪击事件

2023-03-28 05:51:37

当前热讯:春季守护行动|惊险!小车深夜追尾,原来是醉驾惹的祸!

2023-03-28 00:53:22

北京网友拍到超亮火流星划过夜空,专家称或有陨石坠落 世界观热点

2023-03-27 22:03:14

焦点资讯:抢拼保促|向国家级园区冲刺 雨花经开区书写高质量发展新篇章

2023-03-27 20:13:04

庄司惠

2023-03-27 18:57:47

【播资讯】合肥城建:注销公司全资子公司

2023-03-27 17:21:41

开阳县综合施策 做到“四及时”抗旱保春耕 世界报道

2023-03-27 16:15:59

2023山西峨眉山纪念币哪些银行可以预约?(附入口) 当前关注

2023-03-27 15:12:45

英汉句法翻译技巧_关于英汉句法翻译技巧的简介

2023-03-27 13:45:46

每日聚焦:2023高考300分公办本科学校有哪些

2023-03-27 12:11:05

4月20日起北京种植牙费用将大幅降低

2023-03-27 11:08:00

挖掘产业优势 推进乡村振兴(经济聚焦)|环球热消息

2023-03-27 10:14:18

【世界新视野】湖北绿色殡葬逐渐成为新风尚 6万逝者回归自然

2023-03-27 08:50:08

桑树叶的作用和功效及副作用_桑树叶的作用

2023-03-27 06:43:31

火线精英怎么获得血钻_火线精英血钻兑换码

2023-03-27 01:45:07

犬决(关于犬决的介绍)

2023-03-26 21:58:28

聚焦:襄阳襄城:关注心理健康教育 呵护青少年健康成长

2023-03-26 20:02:00

40g藕粉要多少开水?|每日热文

2023-03-26 17:23:30

麒麟红茶拿铁粉_麒麟红茶

2023-03-26 15:25:33

电梯门洞尺寸规范_电梯门洞尺寸

2023-03-26 13:01:08

世界焦点!供的多音字组词

2023-03-26 11:45:51

老人故意推倒摩托车案胜诉 老人儿子需赔1.6万!车主回应|百事通

2023-03-26 10:23:46

天天观点:去年我国光伏行业总产值超1.4万亿元

2023-03-26 08:00:14

环球消息!何超琼向太同框,一个优雅大气,一个扮嫩却显老,差距很明显

2023-03-26 03:59:22

环球即时:歌手王琪个人资料简介_歌手王琪的简介

2023-03-25 22:49:59

荠菜煮鸡蛋吃死人

2023-03-25 22:12:24

天天消息!泰戈尔世界上最遥远的距离向表达什么_泰戈尔 世界上最遥远的距离

2023-03-25 20:14:44

武汉首家“小神闲茶馆”开业,茶颜悦色:可容纳四五十人,主推挂耳手冲茶

2023-03-25 17:11:09

成都国际陆港重点片区来厦开启新合作-环球滚动

2023-03-25 15:01:45

电梯怎样防止坠落|世界资讯

2023-03-25 15:10:32

嘢猫传媒_嘢|世界观点

2023-03-25 12:51:35

锦波生物北交所过会,主营业务并非医美方向依据被追问

2023-03-25 10:25:29

【播资讯】PS+4月离库游戏阵容:《火影忍者疾风传4》等7款

2023-03-25 08:34:59

望尽天涯路原文|热门

2023-03-25 07:28:07

空中客车亚洲总装线总装的首架A321neo飞机交付

2023-03-25 05:56:36

强备战 抓实训 严作风 励精兵

2023-03-25 01:07:40

世界快播:东方碳素通过北交所上市委审核 平顶山A股上市公司有望达到4家

2023-03-24 22:13:40

iPhone15Pro“药丸”大小不变:里面还有距离传感器

2023-03-24 20:07:51

打卡四川美食别错过!来看看“天府名厨”“天府名店”都有哪些 重点聚焦

2023-03-24 18:56:55

云顶之弈弗雷尔地图怎么获得

2023-03-24 18:08:49

榆阳区人民代表大会常务委员会办公室

2023-03-24 17:16:25

ETF观察丨全国中成药集采将启,达仁堂跌停,医药ETF基金(159838)盘中溢价 世界播资讯

2023-03-24 16:30:50

全球聚焦:地产主管的工作计划书(优选3篇)

2023-03-24 15:04:01

焦点资讯:2023中山市神湾镇积分入学政策

2023-03-24 13:02:12

全球最新:浅析:《陈情令》魏无羡衣服之黑灰色图纹拼接束袖长袍

2023-03-24 12:03:19

全球热讯:德国手表品牌mido是什么

2023-03-24 11:04:29

地球是一颗处于不断变化中的星球,我们有理由对我们的家园着迷

2023-03-24 10:43:24

恒大的201页重组方案_当前看点

2023-03-24 09:41:10

全球观天下!Block遭做空,“木头姐”旗下方舟投资管理公司遇双重打击

2023-03-24 08:29:06

维信金科(02003) 2022年报:业绩稳健凸显增长韧性 分红0.1港元/股

2023-03-24 06:17:01

qq4g在线是什么意思_4g在线是什么意思

2023-03-24 01:43:16

动态焦点:中钢协骆铁军:加快国内铁矿资源勘探开发和增储上产金十期货3月23日讯,2023年3月23日,中国钢铁工业协会在安徽马鞍山召开“基石计划”国内铁矿资源开发工作座谈会,中钢协副会长骆铁军强调,下一步工作要继续做好以下四点

2023-03-23 22:21:58

王子文电视剧作品

2023-03-23 21:49:13

体彩23072期晒票:制定明确的购彩计划,注意彩票保密 最新

2023-03-23 20:24:40

孩子咳嗽老不好怎么办呀_孩子咳嗽老不好怎么办-当前观察

2023-03-23 18:58:19

环球热消息:黄金定价模式生变背后:央行们正失去对货币环境的控制

2023-03-23 17:38:59

环球百事通!中国gdp历年数据排名_中国gdp历年数据

2023-03-23 16:05:28

汇通能源(600605)3月23日10点19分触及涨停板|全球短讯

2023-03-23 15:29:24

全国高考时间是什么时候 世界新资讯

2023-03-23 14:25:10

大越期货:预期逐步兑现 钢价走势转震荡 天天新资讯

2023-03-23 14:14:51

世界焦点!Opera 桌面浏览器正式上线生成式 AI 工具

2023-03-23 12:10:04

复星入主舍得酒业两年:营收突破60亿元,业绩翻倍,“白酒一哥”猛加仓_环球热推荐

2023-03-23 11:01:27

不具备安全通行条件 云南独龙江景区临时管制

2023-03-23 09:37:33

颜值更高,质感大涨,还换上1.5T!大众新款探歌这回可算花心思了 世界热推荐

2023-03-23 07:58:45

如何给电脑做系统备份

2023-03-23 06:54:00

红旗飘飘歌词及简谱_红旗飘飘歌词完整版

2023-03-23 04:52:02

共同监管,从严打击!@儋州广大市民,这里有你的一封信-全球快看

2023-03-23 00:15:54

每日焦点!近4轮3败!穆里尼奥执教罗马联赛均分降至1.69,跌出队史前十

2023-03-22 21:10:26

【天天报资讯】任嘉伦的孩子叫什么_任嘉伦的孩子

2023-03-22 19:20:41

使命召唤手游国际服哪里输兑换码,ps4 使命召唤4兑换码怎么用|当前观点

2023-03-22 18:56:32

每日信息:南通公积金缴存基数2023 调整范围如何?

2023-03-22 17:23:45

若非群玉山头见会向瑶台月下逢意思(若非群玉山头见会向瑶台月下逢)

2023-03-22 16:13:05

特斯拉Model 3改款信息曝光 增配明显 或于三季度投产

2023-03-22 14:44:21

天际线ME7、ME-S将登陆成都天际线汽车成都车展 发布战略“客户服务平台”

2023-03-22 12:59:29

英官员称将向乌提供贫铀弹 俄方表示谴责-世界报道

2023-03-22 10:57:40

柳州,只分旺季、螺蛳粉季和紫荆花季 环球视讯

2023-03-22 09:00:02

时讯:孔子学院美国有几所_孔子学院美国中心

2023-03-22 05:57:48

天天快播:国际森林日:自然教育助力绿色“森森”不息

2023-03-22 00:59:02

绿色颜色大全色卡_绿色配什么颜色高级

2023-03-21 21:52:27

每日短讯:臭氧层被破坏的原因是什么哪一年被破坏完_臭氧层被破坏的原因

2023-03-21 19:15:43

当日快讯:龙虎榜 | 吉宏股份今日涨停,深股通专用买入5449.21万元并卖出4578.34万元 独家

2023-03-21 17:10:15

条码软件如何批量制作A级的EAN 13条码

2023-03-21 14:59:05

当日快讯:再出先锋领航退出中国传闻,最新回应:保持之前否认态度不变,相关运营一切如常

2023-03-21 12:47:41

匣组词_匣组词有哪些-天天精选

2023-03-21 11:06:45