JNI到底是个啥

6 篇文章 1 订阅
本文详细解析了Java Native Interface (JNI) 的概念及其在Java虚拟机(JVM)中的作用方式。介绍了JNI如何通过C或C++实现本地方法,以及这些方法是如何加载到JVM中的。此外,还探讨了JNI与垃圾回收之间的相互作用。
摘要由CSDN通过智能技术生成

JNI可能你看点Java的书或者JVM的书,都会提到,但是好像很多就是点到为止,也不具体说一下到底是啥,干什么的,真的是“不讲武德”。

JNI全程是Java Native Interface,一句话来说就是Java的本地接口,和我们常见的很多Java方法,很多实现是由Java本身来实现的,有的时候还需要本地方法来提供相关的功能。

说一句白话,就是我们平常一提到Java就说,“跨平台,可移植性强”,但是问题也来了,很多平台专门提供的能力有时候你就用不到了,A家有B家没有,你又想在A家平台用,也就说这些功能实际上还需要平台来提供。

JNI是什么

既然是JNI,I是interface接口的意思,那他和别的接口有啥区别?都是接口的话,我哪知道你是本地的还是外地的。还有就是JNI的实现方法在哪里?

区别:JNI对应的接口实际上就是我们看源码经常遇到的native修饰的方法,这样的方法也很独特,跟接口里面的方法一样,没有方法的具体实现,用native来修饰。

我用Object里的hashcode来举例子,这个hashcode可是以后对对象加锁的一个根据,不要小看他:

  /**
     * Returns a hash code value for the object. This method is
     * supported for the benefit of hash tables such as those provided by
     * {@link java.util.HashMap}.
     * <p>
     * The general contract of {@code hashCode} is:
     * <ul>
     * <li>Whenever it is invoked on the same object more than once during
     *     an execution of a Java application, the {@code hashCode} method
     *     must consistently return the same integer, provided no information
     *     used in {@code equals} comparisons on the object is modified.
     *     This integer need not remain consistent from one execution of an
     *     application to another execution of the same application.
     * <li>If two objects are equal according to the {@code equals(Object)}
     *     method, then calling the {@code hashCode} method on each of
     *     the two objects must produce the same integer result.
     * <li>It is <em>not</em> required that if two objects are unequal
     *     according to the {@link java.lang.Object#equals(java.lang.Object)}
     *     method, then calling the {@code hashCode} method on each of the
     *     two objects must produce distinct integer results.  However, the
     *     programmer should be aware that producing distinct integer results
     *     for unequal objects may improve the performance of hash tables.
     * </ul>
     * <p>
     * As much as is reasonably practical, the hashCode method defined by
     * class {@code Object} does return distinct integers for distinct
     * objects. (This is typically implemented by converting the internal
     * address of the object into an integer, but this implementation
     * technique is not required by the
     * Java&trade; programming language.)
     *
     * @return  a hash code value for this object.
     * @see     java.lang.Object#equals(java.lang.Object)
     * @see     java.lang.System#identityHashCode
     */
    public native int hashCode();

代码只有一行,解释是他的几十倍。

JNI的实现:
实际上是由C或者C++语言来实现,为了和其它的方法实现做个对比,我先来一个JVM的图,Java方法栈针对的是Java的方法栈,而本地方法栈针对的就是针对本平台一些C实现的方法等的实现
在这里插入图片描述

JNI是怎么混进JVM的
那这个本地方法怎么混进JVM的本地方法栈的,毕竟JVM也有一套自己的加载机制,不是说你写一个方法JVM就会去加载。

所以JNI的具体实现的方法加载是怎么样的?实际上JNI的C语言方法加载大概分成两部分:“主动型”,“被动型”。这些都是我创造的词,这里的主动被动是JVM为主体来体现的。

主动的:JVM会根据native方法去找对应的C语言,JVM查找是根据一定命名规则来查找,毕竟Java和C是不同的语言,有不同的规范

查找的规则:native对法对应C函数一般是Java_开头,后面跟着包名和方法名(Java的native方法的包和类名),比如:

Java_org_example_Foo_foo

方法的写法格式不一样,C不支持的怎么办,比如说斜杠“\”之类的,那就把Java的“\”替换为"_",同理还有类似的替换的有:

Java的“_” 替换为C的"_1"
Java的“;” 替换为C的"_1"
Java的“[” 替换为C的"_1"

被动型:首先要有一个“主动”的C函数方法实现,被JVM加载,然后吊起的方法里面会有其他对应的native方法实现,于是这些方法没有按照规则命名,被动的加载进来。

比如说有一个方法叫做registerNatives方法,放在类里面的静态块里,加载的时候第一个加载,然后把里面的native方法都带上

这种“主动”的方法里面,例子如下:


// 注:Object类的registerNatives方法的实现位于java.base模块里的C代码中
static JNINativeMethod methods[] = {
    {"hashCode",    "()I",                    (void *)&JVM_IHashCode},
    {"wait",        "(J)V",                   (void *)&JVM_MonitorWait},
    {"notify",      "()V",                    (void *)&JVM_MonitorNotify},
    {"notifyAll",   "()V",                    (void *)&JVM_MonitorNotifyAll},
    {"clone",       "()Ljava/lang/Object;",   (void *)&JVM_Clone},
};

JNIEXPORT void JNICALL
Java_java_lang_Object_registerNatives(JNIEnv *env, jclass cls)
{
    (*env)->RegisterNatives(env, cls,
                            methods, sizeof(methods)/sizeof(methods[0]));
}

你看methods这个就是正规Java的命名。

JNI的API

JNI也有API,这里是Oracle列出来的,也没去比较和OpenJDK的区别
JNI API

JNI和垃圾回收

实际上JNI也会生成对象,拿着对象会不会被回收?会但是一般来说不会轻易回收,JNI有局部引用和全部引用,不管是哪个,都会被JVM标为“不可回收”,只不过局部引用会在native方法返回失效,可以作为回收的对象

微信公众号:我是坑货
在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值