前言
早上debug join方法的时候,其内部调用wait方法,wait是Object中的native方法,但是在ClassLoader类中的findNative中打断点,不会进去断点。然后想了一下,是不是因为Object是Bootstrap类加载器加载的原因。
那么怎么才能知道native调用的到底是什么方法呢?在网上搜索"Java如何查看native方法的实现",没有搜到可用的内容。
索性自己去翻一下hostspot jdk的源码,我下载的是openjdk-8u40-src-b25-10_feb_2015.zip,可以从openjdk官网下载。
举个例子,比如我要搜索Object中的wait方法:
1、openjdk目录结构分析(有助于快速定位源码位置)
请原谅我眼花缭乱的框选,打开Object.c看看:
2、初见Object.c
从wait方法入口进去,实现在jvm.cpp中
JDK中用到的jni接口,最终都会在jvm.h文件中定义,并在jvm.cpp中作为C++实现的入口,也就是说jvm.cpp是Java世界和JVM中C++世界沟通的桥梁。
JVMWrapper("JVM_MonitorWait");这一句是定义了一个宏
看一下270行,我搜了下Histogram的意思,是直方图,猜测这里只是在做JVM统计,或者为了监控而调用的逻辑。这里先略过。
2.1 使用oop指针指向Java对象
接着看这行:
是把当前执行的java类包装成一个Handle类型,Handle类型,见下图,将Java对象赋值给了一个oop指针类型。
2.2 紧接着这行:JvmtiExport::should_post_monitor_wait(),553行
should_post_monitor_wait默认false,在jvmtiEventController.cpp中的recompute_enabled方法中会进行设置,搜了下recompute_enabled在jvmtiEventController.cpp有多处调用,从名字上看可能有事件驱动的逻辑,should_post_monitor_wait的值应该也是响应时间设置的。
有哪些事件?导致wait方法的这个should_post_monitor_wait变量变化的是哪些事件?
在Java中通过JNI接口可以实现Java调用本地方法;通过JVMTI接口可以实现在C++空间调用Java对象的方法。
jvmtiEventController.cpp中的recompute_enabled的部分方法体:
再看JvmtiExport::post_monitor_wait((JavaThread *)THREAD, (oop)obj(), ms);这行。
小结:
写的好乱,很多细节没怎么懂,看了if语句块中的注释,这段的意思是:当前线程已经拥有监视器,但是没被加到等待队列中,JVMTI_EVENT_MONITOR_WAIT事件没办法处理unpark(),意思应该就是没办法释放锁。
那post_monitor_wait这个意思应该就是推迟监视器的等待,就是先不释放锁。
2.3 接着看ObjectSynchronizer::wait(obj, ms, CHECK);
这个调用的实现在synchronizer.cpp文件中,
1)首先,如果UseBiasedLocking为true,使用偏向锁
2)如果millis < 0,抛出异常
3)inflate()中是锁膨胀升级逻辑
4)调用objectMonitor.cpp中的wait方法。wait的大部分逻辑在这里。可以参见延伸阅读[1]
总结:
本文通过介绍openjdk底层源码的目录结构,wait方法执行涉及到的调用关系。对从Java方法调用到C++代码调用有一个感性的认识。具体C++代码逻辑,还需要进一步分析。
延伸阅读:
[1] JVM源码分析之Object.wait/notify实现
[2] 并发编程的艺术
关于搜索技巧:
文章开头提到,在网上搜索"Java如何查看native方法的实现",没有搜到可用的内容。然后在看源码的过程中,看到C++代码里的这个方法JVMWrapper。不是很明白,就去搜狗微信上搜索了JVMWrapper。
搜索到了源码分析:Java中的Thread的创建和运行 这篇文章。