Network Security Internet Technology Development Database Servers Mobile Phone Android Software Apple Software Computer Software News IT Information

In addition to Weibo, there is also WeChat

Please pay attention

WeChat public account

Shulou

How to implement the default hashCode method of translation jdk

2025-01-17 Update From: SLTechnology News&Howtos shulou NAV: SLTechnology News&Howtos > Development >

Share

Shulou(Shulou.com)06/03 Report--

This article mainly introduces "how to achieve the default hashCode method of translation jdk". In daily operation, I believe that many people have doubts about how to achieve the default hashCode method of translation jdk. The editor has consulted all kinds of materials and sorted out simple and easy-to-use operation methods. I hope it will be helpful to answer the doubts of "how to realize the default hashCode method of translation jdk"! Next, please follow the editor to study!

A trivial problem.

In my work last week, I submitted a trivial change to a class, implementing the toString () method to make logging more useful. To my surprise, the change led to a decline in coverage of about 5%. I know that all the new code is covered by existing unit tests, but coverage has declined, so what went wrong?

In contrast to the previous coverage report, a keen colleague found that the unit test covered the implementation of HashCode () before the code, but not after the changes. Of course, this is true: the default ToString () calls hashcode (), but the modified one doesn't.

Public String toString () {return getClass () .getName () + "@" + Integer.toHexString (hashCode ());}

After rewriting the toString, our custom hashCode is no longer called, so the coverage is reduced. Everyone knows how the default toString implementation works, but.

How is the default hashCode method implemented?

The default hashCode () returns a unique hash code (identity hash code). Note that this is not the same thing as rewriting the hash code returned by hashCode. If a class overrides the hashCode method, we can also use System.identityHashCode (o) to get its unique hash code (which feels like the ID number of the object).

It is generally believed that the only hash code uses the corresponding integer of the memory address of the object. ), but the java api documentation says:

... Is typically implemented by converting the internal address of the object into an integer, but this implementation technique is not required by the Java ™programming language. A typical implementation is to convert the memory address of an object to an integer, but this implementation technique is not necessary for the java platform.

Given that JVM will relocate the object (for example, due to promotion or compression during garbage collection), we must keep it after we calculate the object's identity hash code.

Default hashCode implementation

For the default hashCode method, different JVM may be implemented in different ways. This article only looks at the source code of openJDK. HashCode is the native method. The entry is as follows: src/share/vm/prims/jvm.h and src/share/vm/prims/jvm.cpp.

508 JVM_ENTRY (jint, JVM_IHashCode (JNIEnv* env, jobject handle)) 509 JVMWrapper ("JVM_IHashCode"); 510 / / as implemented in the classic virtual machine; return 0 if object is NULL511 return handle = = NULL? 0: ObjectSynchronizer::FastHashCode (THREAD, JNIHandles::resolve_non_null (handle)); 512 JVM_END

Then the ObjectSynchronizer::FastHashCode () file is src/share/vm/runtime/synchronizer.cpp. People might naively think that the method is as simple as the following:

If (obj.hash () = = 0) {obj.set_hash (generate_new_hash ());} return obj.hash ()

But there are actually hundreds of lines. If you look at the file name, you probably know that synchronization is involved here, that is, the implementation of synchronized, yes, the object built-in lock. We'll talk about this later, first looking at how to generate a unique hash code.

Static inline intptr_t get_next_hash (Thread* self, oop obj) {intptr_t value = 0; if (hashCode = = 0) {/ / This form uses global Park-Miller RNG. / / On MP system we'll have lots of RW access to a global, so the / / mechanism induces lots of coherency traffic. Value = os::random ();} else if (hashCode = = 1) {/ / This variation has the property of being stable (idempotent) / / between STW operations. This can be useful in some of the 1-0 / / synchronization schemes. Intptr_t addr_bits = cast_from_oop (obj) > > 3; value = addr_bits ^ (addr_bits > > 5) ^ GVars.stw_random;} else if (hashCode = = 2) {value = 1; / / for sensitivity testing} else if (hashCode = = 3) {value = + GVars.hc_sequence;} else if (hashCode = = 4) {value = cast_from_oop (obj) } else {/ / Marsaglia's xor-shift scheme with thread-specific state / / This is probably the best overall implementation-we'll / / likely make this the default in future releases. Unsigned t = self- > _ hashStateX; t ^ = (t _ hashStateX = self- > _ hashStateY; self- > _ hashStateY = self- > _ hashStateZ; self- > _ hashStateZ = self- > _ hashStateW; unsigned v = self- > _ hashStateW; v = (v ^ (v > > 19)) ^ (t > > 8); self- > _ hashStateW = v; value = v;} value & = markWord::hash_mask; if (value = 0) value = 0xBAD Assert (value! = markWord::no_hash, "invariant"); return value;} 0. A randomly generated number. Random number 1. A function of memory address of the object. Memory address function 2.A hardcoded 1 (used for sensitivity testing.) The hard code is the number 13. A sequence. Self-increasing sequence 4. The memory address of the object, cast to int. The memory address is strongly converted to int5. Thread state combined with xorshift (https://en.wikipedia.org/wiki/Xorshift) thread state federated xorshift

According to src/share/vm/runtime/globals.hpp, the production environment is 5, or xorshift, which should also be a random number scheme.

1127 product (intx, hashCode, 5,\ 1128 "(Unstable) select hashCode generation algorithm")\

Openjdk8 and 9 use 5Med OpenJDK 7 and 6 and use the first scheme (that is, the random number scheme).

Object header and synchronization

In openjdk, mark word is described as follows: see here for details

30 / / The markOop describes the header of an object.31 / 32 / / Note that the mark is not a real oop but just a word.33 / / It is placed in the oop hierarchy for historical reasons.34 / / 35 / / Bit-format of an object header (most significant first Big endian layout below): 36 / 37 / 32 bits:38 / /-39 / / hash:25-> | age:4 biased_lock:1 lock:2 (normal object) 40 / / JavaThread*:23 epoch:2 age:4 biased_lock:1 lock:2 (biased object) 41 / / size:32- -- > | (CMS free block) 42 / / PromotedObject*:29-> | promo_bits:3-> | (CMS promoted object) 43 / / 44 / / 64 bits:45 / /-46 / / unused:25 hash:31-- > | unused:1 Age:4 biased_lock:1 lock:2 (normal object) 47 / / JavaThread*:54 epoch:2 unused:1 age:4 biased_lock:1 lock:2 (biased object) 48 / / PromotedObject*:61-> | promo_bits:3-> | (CMS promoted object) 49 / / size:64- -- > | (CMS free block) 50 / / 51 / / unused:25 hash:31-> | cms_free:1 age:4 biased_lock:1 lock:2 (COOPs & & normal object) 52 / / JavaThread*:54 epoch:2 cms_free:1 age:4 biased_lock:1 lock:2 (COOPs & & biased object) 53 / / narrowOop: 32 unused:24 cms_free:1 unused:4 promo_bits:3-> | (COOPs & & CMS promoted object) 54 / / unused:21 size:35-> | cms_free:1 unused:7-> | (COOPs & & CMS free block)

The mark word format is slightly different in 32 and 64 bits. The latter has two variants, depending on whether compressed object pointers are enabled. By default, both Oracle and OpenJDK 8 are executed. If the object is in a biased locked state, then 23bit stores pointers biased to threads, so where can I get a unique hash code?

Bias lock

The biased state of the object is caused by the biased lock. Starting with hotspot6, try to reduce the cost of locking an object. These operations are expensive because their implementation usually relies on atomic CPU instructions (CAS) to safely handle lock / unlock requests on objects on different threads. However, according to the analysis, in most applications, most objects are locked by only one thread, so the execution of the above atomic instructions is a waste (cas instructions are already fast, much faster than context switching, and also a waste. To avoid this waste, the lock-biased JVM allows threads to bias objects towards themselves If an object is eccentric, the lucky thread does not even need to execute cas instructions to lock and unlock, only if there are no multiple threads fighting for the same object, the performance of the lock bias will be very good. Continue to look at FastHashCode:

601 intptr_t ObjectSynchronizer::FastHashCode (Thread * Self, oop obj) {602 if (UseBiasedLocking) {610 if (obj- > mark ()-> has_bias_pattern ()) {. 617 BiasedLocking::revoke_and_rebias (hobj, false, JavaThread::current ());... 619 assert (! obj- > mark ()-> has_bias_pattern (), "biases should be revoked by now"); 620} 621}

When a unique hash code is generated, the existing bias is undone and the biasing ability of this object is disabled (false means do not try to re-bias), which is indeed unchanged after a few lines of the above code:

637 / / object should remain ineligible for biased locking638 assert (! mark- > has_bias_pattern (), "invariant")

This means that requesting a unique hash code for an object disables the object's bias lock, and trying to lock the object requires expensive atomic instructions, even if only one thread requests the lock.

Why does the bias lock conflict with the unique hash code?

To answer this question, we must know what the possible locations of markup words are, depending on the locked state of the object. From the sample diagram of HotSpot Wiki, there is the following conversion:

At this point, the study of "how to implement the default hashCode method of translation jdk" is over. I hope to be able to solve your doubts. The collocation of theory and practice can better help you learn, go and try it! If you want to continue to learn more related knowledge, please continue to follow the website, the editor will continue to work hard to bring you more practical articles!

Welcome to subscribe "Shulou Technology Information " to get latest news, interesting things and hot topics in the IT industry, and controls the hottest and latest Internet news, technology news and IT industry trends.

Views: 0

*The comments in the above article only represent the author's personal views and do not represent the views and positions of this website. If you have more insights, please feel free to contribute and share.

Share To

Development

Wechat

© 2024 shulou.com SLNews company. All rights reserved.

12
Report