架构
- Object.java(rt.jar) 调用 jdk的native方法(Object.c)。
- native方法 调用hotspot jvm的方法(jvm.cpp)。
Object.java
- java source版本:oracle 1.7
Object 还有隐形的构造函数.
1 | new Object(); |
疑问:
为什么Object.java中看不到构造函数
编译器为它生成了构造函数
为什么在stack trace中看不到调用Object.
有7个native方法。
- private static native void registerNatives();
- protected native Object clone() throws CloneNotSupportedException;
- public final native Class<?> getClass();
- public native int hashCode();
- public final native void notify();
- public final native void notifyAll();
- public final native void wait(long timeout) throws InterruptedException;
- 但是构造函数是怎样实现的呢?(见jvm目录的init.md)
由于Object类中有JNI方法调用,按照JNI的规则,应当生成JNI 的头文件。
在此目录下执行javah -jni java.lang.Object 指令,将生成一个java_lang_Object.h头文件(自动生成的header,没什么意义)
Object.c
- source版本:openjdk-7-fcs-src-b147-27_jun_2011
- 路径: openjdk\jdk\src\share\native\java\lang\Object.c
- 没有Object.h
Object.c
1 | /*- |
其中JNINativeMethod的结构体如下:
1 | typedef struct { |
跟踪 hashcode
1 | // jvm.h 路径: openjdk\hotspot\src\share\vm\prims\jvm.h |
FastHashCode才是真正计算hashcode的代码
FastHashCode
这是hashCode()的具体实现
1 | // 路径: openjdk\hotspot\src\share\vm\runtime\synchronizer.cpp |
get_next_hash
这才是核心代码
又调用的get_next_hash()
1 | // 路径: openjdk\hotspot\src\share\vm\runtime\synchronizer.cpp |
hashCode()并不是简单的返回内存地址。
OpenJDK一共实现了5中不同的计算hash值的方法,通过
这段代码中hashCode进行切换。其中hashCode == 4的是直接使用地址的(前面的实验说明OpenJDK默认情况下并没有使用这种方式,或许可以通过运行/编译时参数进行选择)。
结论
前面通过JNI验证已经能够得到很显然的结论,hashCode返回的并不一定是对象的(虚拟)内存地址,具体取决于运行时库和JVM的具体实现。
跟踪wait
1 | JNIEXPORT void JNICALL |
跟踪notify
1 | JNIEXPORT void JNICALL |
跟踪clone
1 | JNIEXPORT jobject JNICALL |
跟踪 getClass
跟踪
参考
http://blog.csdn.net/xusiwei1236/article/details/45152201
byte code
- 通过编译后的jar包(即class文件),查看byte code.
- 运行 javap -c java.lang.Object > a.txt,得到以下的byte code
如果执行不成功,看看是否把jdk的lib加入到了classpath:
1 | Compiled from "Object.java" |
C:\Program Files\java\jdk1.7.0_67\jre\lib\rt>
其他
- object header: it’s JVM dependent, 具体参考JVM
扩展阅读
- Object.hashCode()的返回值到底是不是对象内存地址