-2

I know Object.hashCode() does not necessarily be related to memory address. But I am trying to understand when it does, how it works.

I checked the code. The Object code declares hashCode() as native:

public native int hashCode();

I basically dont understand how this native works.

I found below two related files:

Object.c contains [source]:

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},
};

java_lang_Object.h contains [source]:

/*
 * Class:     java_lang_Object
 * Method:    hashCode
 * Signature: ()I
 */
JNIEXPORT jint JNICALL Java_java_lang_Object_hashCode
  (JNIEnv *, jobject);

However all that is not making sense. More importantly I dont find actual native implementation of hashCode() in above files and I dont understand JNI and possibly some advanced C well. Can someone explain how all things are getting wired up?

MsA
  • 2,599
  • 3
  • 22
  • 47
  • .h is a header file, the actual implementation is in .c file: https://github.com/cscott/Harpoon/blob/master/Runtime/src/sunjdk/java.lang/java_lang_Object.c – Alex Sveshnikov Mar 18 '20 at 08:14
  • ok but can you please explain a bit how java call translates to native call for quick understanding? Seems that I have to dig in JNI and C for hours... – MsA Mar 18 '20 at 08:20
  • @anir an implementation can be found [here](https://github.com/cscott/Harpoon/blob/bcec08dbbaed226fe653203e18d6a2c3a8b105a9/Runtime/src/java.lang/system.h) – Lino Mar 18 '20 at 08:51
  • @Lino: that is nothing to do with the *real* JVM implementation of identity hashcode. – Stephen C Mar 18 '20 at 10:48

2 Answers2

1

Seems that I have to dig in JNI and C for hours...

Nope.

Step 1: Download the source tree to a local disk. (Ideally an SSD, but if you are using Linux and have plenty of memory that is almost as good.)

Step 2: Learn how to chain find, xargs and grep together. For example:

  find . -name \*.c -type f | xargs grep Java_java_lang_Object_hashCode | less

takes the names of all C source files in the current tree and searches the file contents for the function that corresponds to the declaration that you found. Check out the manual entries for useful command options; e.g. for doing case insensitive search.

(For Mac OS, the same commands should work. For Windows .... >>shrug<<.)

Step 3: start digging.

It is not necessary to understand exactly how JNI works to trace the native code execution paths in the JNI codebase. Just follow the function calls until you get to the actual implementations.

Hint: in this case, &JVM_IHashCode is a function pointer. So start looking for where the JVM_IHashCode function is declared.


A couple of wrinkles:

  • The JVM codebase consists of Java, C and C++, so there are actually 5 different file types that are relevant; .java, .c, .h, .cpp and .hpp.

  • There are few places where code is generated from template files.

  • There was a big file reorganization between Java 8 and Java 9. A lot of stuff moved to different directories. It is to do with modules.

Stephen C
  • 698,415
  • 94
  • 811
  • 1,216
  • I know asking for how JNI is working in this case of `hashCode()` is like trying to take shortcut to understand the things...but still I was trying whether I can understand by simply going through / browsing jdk source in github. Can someone tell how the code in the files I noted in the question work together? – MsA Mar 18 '20 at 10:18
  • *"I was trying whether I can understand by simply going through / browsing jdk source in github."* - You are making things hard for yourself! Just download the lot is my advice. – Stephen C Mar 18 '20 at 10:40
  • *"Can someone tell how the code in the files I noted in the question work together?"* - 1) I won't. I would need to do more research than I am prepared to do. 2) It won't answer your real question anyway. Your real is finding the actual native implementation of `hashCode`. An intimate understanding of JNI mechanisms won't help you find it. Focus on the details that actually matter. – Stephen C Mar 18 '20 at 10:45
0

Yes, you will have to dig through JNI code. It's just a matter of searching code.

Taking my local copy of JDK9 (rev b756e7a2ec33):

  • JVM_IHashCode (src/share/vm/prims/jvm.cpp) calls
  • ObjectSynchronizer::FastHashCode (src/share/vm/runtime/synchronizer.cpp), which has several paths that either read a cached value or take the result of
  • get_next_hash (same file), which dispatches on the value of a global hashCode setting, which is defined in
  • src/share/vm/runtime/globals.hpp as an experimental global with a default of 5.

Summarizing the various options for hashCode:

  • 0: random value
  • 1: derived from the address and something called "stwRandom"
  • 2: always 1
  • 3: increasing counter
  • 4: direct address of the object
  • 5: something called "Marsaglia's xor-shift scheme with thread-specific state", which does not involve the object address.
Botje
  • 26,269
  • 3
  • 31
  • 41