★08.缓存属性和方法ID

简介

  • 在获取一个 属性/方法ID 的时候需要基于名称或者 属性/方法描述符符号查找符号查找 的代价相对来说是比较昂贵的(消耗时间和资源),优化主要思路的是计算 属性/方法ID 通过缓存以供后续使用。
  • 有两种缓存方式,如有可能应该尽量使用后者: 用时缓存类静态初始化器缓存

用时缓存

简单示例

JNIEXPORT void JNICALL Java_InstanceFieldAccess_accessField(JNIEnv * env, jobject obj) {
    // 静态局部变量以便于一次获取,以后就不必重新获取
    static jfieldID fid_s = NULL;

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

    // 只有从来没获取fid_s才会获取
    if (!fid_s) {
        fid_s = (* env)->GetFieldID(env, cls, "s", "Ljava/lang/String;");
        if (!fid_s) {
            return;
        }
    }

    jstring jstr = (* env)->GetObjectField(env, obj, fid_s);
    const char * str = (* env)->GetStringUTFChars(env, jstr, NULL);
    if (!str) {
        return;
    }
    printf("In C: \n");
    printf("c.s = \"%s\"\n", str);
    (* env)->ReleaseStringUTFChars(env, jstr, str);
    jstring newJstr = (* env)->NewStringUTF(env, "123");
    if (!newJstr) {
        return;
    }
    (* env)->SetObjectField(env, obj, fid_s, newJstr);
}

示例解说

  • 示例中的属性IDfid_s使用了静态局部存储,用以缓存,重复使用时不再重新获取。

优缺点

  • 优点 :非侵入性的,即在对 Java 代码没有控制权的时候,仍然可以用 用时缓存 ,而 类静态初始化器缓存 的方法则不可以。
  • 缺点
    • 在多线程的情况下,可能会出现fid_s重复计算/缓存/检查 的问题。在此处fid_s重复计算/缓存 除了有一部分性能开销以外,基本是无害的。
    • 当类被载出时,缓存的ID不再有效,需要获取,在使用 用时缓存 的方法时,是需要保证当原生代码仍然在用缓存ID时,类不会被载出或重新加载。

类静态初始化器缓存

简单示例

public class InstanceMethodCall {
    static {
        System.loadLibrary("InstanceMethodCall");
        // 在类静态初始化代码块中缓存ID
        initIDs();
    }

    public static void main(String args[]) {
        InstanceMethodCall c = new InstanceMethodCall();
        c.nativeMethod();
    }

    // 类静态函数,实现交给原生代码,用于缓存ID
    private static native void initIDs();

    private native void nativeMethod();

    private void callback() {
        System.out.println("In Java");
    }
}
// 创建全局变量,以便于ID可以在多个不同的原生函数中传递
jmethodID MID_InstanceMethodCall_callback;

JNIEXPORT void JNICALL Java_InstanceMethodCall_initIDs(JNIEnv * env, jclass cls) {
    // 获取所有需要缓存的ID到全局变量中
    MID_InstanceMethodCall_callback = (* env)->GetMethodID(env, cls, "callback", "()V");
}

JNIEXPORT void JNICALL Java_InstanceMethodCall_nativeMethod(JNIEnv * env, jobject obj) {
    printf("In C\n");
    // 使用缓存的ID
    (* env)->CallVoidMethod(env, obj, MID_InstanceMethodCall_callback);
}

示例解说

  • Java 代码中声明一个静态native函数initIDs()用于缓存ID。
  • Java 代码中 类静态构造代码块 中调用initIDs()
  • 在原生代码中实现initIDs(),缓存ID到全局变量。

优缺点

  • 优点 :不需要手动获取缓存ID,当类载入或重新加载时,ID会自动缓存。
  • 缺点 :侵入性,无法在对 Java 代码没有控制权的情况下使用。

两种方法的性能比较

概念

  • Java/native调用 :原生代码调用 Java 函数。
  • native/Java调用Java 代码调用原生函数。
  • Java/Java调用Java 代码调用 Java 函数。

Java/native调用

  • Java/native调用 可能慢于 Java/Java调用 ,原因是:
    • 不得不执行额外的操作。
    • 原生代码调用 Java 函数难以内联。
  • 经典的虚拟机执行 Java/native调用 会2-3倍慢于 Java/Java调用 ,但是构建一个虚拟机使得二者的性能开销接近甚至相等也是可能的。

native/Java调用

  • 理论上 native/Java调用 相比 Java/Java调用 会慢2-3倍,但是 native/Java调用 比较罕见。
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,335评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,895评论 3 387
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,766评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,918评论 1 285
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,042评论 6 385
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,169评论 1 291
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,219评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,976评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,393评论 1 304
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,711评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,876评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,562评论 4 336
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,193评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,903评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,142评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,699评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,764评论 2 351

推荐阅读更多精彩内容

  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 171,900评论 25 707
  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,644评论 18 139
  • 2017年6月29号,我毕业了,当学生证在注销的那一刻,我对着宿友说了一句“我感觉心好痛”,虽然这起初是一个网络用...
    一只叫上官薇的大气喵阅读 613评论 5 13
  • 这里主要说一下,在写nodebb插件的时候,遇到的有关css属性操作的问题。 W3School上面是这个样子的 $...
    seafruit阅读 268评论 2 0
  • 现在你还记得年少的记忆吗?或许是你的她?或许是她的你? 2017年7月27日 星期四 天气晴 初识诗人壳应该是...
    苏四夕阅读 179评论 0 0