Java方法签名与JNI,反射

http://blog.houzhi.me/2016/03/19/java-signature-reflect-jni

在这段时间写东西,必须要先吐槽一下找实习的杯具。找个实习不容易,没经验,各种跪。

一直都觉得在Java反射中,那些反射的方法调用都很有规律,每一个调用都需要相同的特性:函数对象(Method),函数参数,类对象。今天坐在电脑前又回忆了JNI的调用方式(C++调用Java),也需要相同的内容:函数ID(jmethodID),参数,类对象(jobject),JNIEnv。仔细一比较,其实两者就是一样的,都是Java方法签名

记得刚学Java的时候,也有特别将Java方法签名,那时候就基本是记下了,但是根本没想到Java方法签名意味着什么,现在终于是能深切体会一些了。这个签名就表示了Java方法,相当于它的ID,适用于Java整个环境,能够通过指定这些内容,形容一次函数调用。我们平时采用普通方式调用Java函数,其实也就是先描述了函数,参数,类对象。其实在Java层,我觉得可以理解为隐含了一个线程描述(JVM)。在native里面,就有个JNIEnv(线程本地变量)描述一个Java虚拟机环境。至于到了java的.class文件里面也是一样的包含了这些标志。下面是截取了一段Constant poll中的内容,里面指定了类StringBuilder,方法参数String,

#12 = Methodref          #7.#55         //  java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;

下面是.class文件方法段里面的stack代码,

21: invokevirtual #12                 // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder;

只是感性的认识,如果把全部的.class 文件通过javap -verbose 的内容都贴上来,实在太囧了。对于invokevirtual命令可以参考这里的http://book.51cto.com/art/200906/131732.htm。如果想要了解,需要对虚拟机指令的操作方式有所了解,那个东东跟汇编有点类似。

关于java方法签名,官网上面有介绍java method signatures。Java的方法声明具有下面几个组件:

  1. 访问标志(public,private…)
  2. 返回类型
  3. 方法名
  4. 参数列表
  5. 异常表
  6. 方法体

但是Java方法中真正被判断是否是同一个方法的签名与上面是不一致的,就像我们熟知的方法重载一样。正如method signatures 所说,它在内部真正具体标记意义的是方法名称和参数列表,因为这种都是在同一个类里面讲重载的,真正算起来应该还要加上具体的类方法,以及具体JVM线程。所以JNI和反射的调用其实就是指定了函数实际的标记:JVM,类对象,方法ID(Method,jmethodID),参数列表。

所以如果需要对各种方式的Java调用进行完全的认识,就需要熟记Java这几种签名标记的特性。如果在实际编码过程中,想要去调用一个方法,那么一定要获取对应的对象,方法名,方法参数。如果是可能存在不同的虚拟机环境,那还得加上虚拟机环境的标记(类似JNIEnv)。当然C/C++的虚拟机中,由于C/C++中int,Object并没有统一父对象,C/C++ JNI提供了针对不同的返回类型,对应不同的调用函数。


好好学习

你可能感兴趣的:(java高级特性)