JNI到底是个啥

系统管理员 2022-12-26 10:18 305阅读 0赞

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可是以后对对象加锁的一个根据,不要小看他:

  1. /**
  2. * Returns a hash code value for the object. This method is
  3. * supported for the benefit of hash tables such as those provided by
  4. * {@link java.util.HashMap}.
  5. * <p>
  6. * The general contract of {@code hashCode} is:
  7. * <ul>
  8. * <li>Whenever it is invoked on the same object more than once during
  9. * an execution of a Java application, the {@code hashCode} method
  10. * must consistently return the same integer, provided no information
  11. * used in {@code equals} comparisons on the object is modified.
  12. * This integer need not remain consistent from one execution of an
  13. * application to another execution of the same application.
  14. * <li>If two objects are equal according to the {@code equals(Object)}
  15. * method, then calling the {@code hashCode} method on each of
  16. * the two objects must produce the same integer result.
  17. * <li>It is <em>not</em> required that if two objects are unequal
  18. * according to the {@link java.lang.Object#equals(java.lang.Object)}
  19. * method, then calling the {@code hashCode} method on each of the
  20. * two objects must produce distinct integer results. However, the
  21. * programmer should be aware that producing distinct integer results
  22. * for unequal objects may improve the performance of hash tables.
  23. * </ul>
  24. * <p>
  25. * As much as is reasonably practical, the hashCode method defined by
  26. * class {@code Object} does return distinct integers for distinct
  27. * objects. (This is typically implemented by converting the internal
  28. * address of the object into an integer, but this implementation
  29. * technique is not required by the
  30. * Java™ programming language.)
  31. *
  32. * @return a hash code value for this object.
  33. * @see java.lang.Object#equals(java.lang.Object)
  34. * @see java.lang.System#identityHashCode
  35. */
  36. 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方法的包和类名),比如:

  1. Java_org_example_Foo_foo

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

  1. Java的“_ 替换为C"_1"
  2. Java的“;” 替换为C"_1"
  3. Java的“[” 替换为C"_1"

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

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

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

  1. // 注:Object类的registerNatives方法的实现位于java.base模块里的C代码中
  2. static JNINativeMethod methods[] = {
  3. {"hashCode", "()I", (void *)&JVM_IHashCode},
  4. {"wait", "(J)V", (void *)&JVM_MonitorWait},
  5. {"notify", "()V", (void *)&JVM_MonitorNotify},
  6. {"notifyAll", "()V", (void *)&JVM_MonitorNotifyAll},
  7. {"clone", "()Ljava/lang/Object;", (void *)&JVM_Clone},
  8. };
  9. JNIEXPORT void JNICALL
  10. Java_java_lang_Object_registerNatives(JNIEnv *env, jclass cls)
  11. {
  12. (*env)->RegisterNatives(env, cls,
  13. methods, sizeof(methods)/sizeof(methods[0]));
  14. }

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

JNI的API

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

JNI和垃圾回收

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

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

发表评论

表情:
评论列表 (有 0 条评论,305人围观)

还没有评论,来说两句吧...

相关阅读

    相关 构造方法到底

    来来来,搞这个构造方法之前我们来看看啥是方法,方法就是一些语句凑在一块实现一些功能的集合,方法通常由两部分组成:参数和返回值。 参数是进入方法里面的数据,通过方法体里面的语句

    相关 JNI到底

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