本文共 4543 字,大约阅读时间需要 15 分钟。
以JDK8为例来分析
public native String intern();
openjdk8\openjdk\jdk\src\share\native\java\lang\String.c
#include "jvm.h"#include "java_lang_String.h"JNIEXPORT jobject JNICALLJava_java_lang_String_intern(JNIEnv *env, jobject this){ return JVM_InternString(env, this);}
openjdk8\openjdk\hotspot\src\share\vm\prims\jvm.cpp
JVM_ENTRY(jstring, JVM_InternString(JNIEnv *env, jstring str)) JVMWrapper("JVM_InternString"); JvmtiVMObjectAllocEventCollector oam; if (str == NULL) return NULL; oop string = JNIHandles::resolve_non_null(str); oop result = StringTable::intern(string, CHECK_NULL); return (jstring) JNIHandles::make_local(env, result);JVM_END
openjdk8\openjdk\hotspot\src\share\vm\classfile\symbolTable.cpp中找到
oop StringTable::intern(Symbol* symbol, TRAPS) { if (symbol == NULL) return NULL; ResourceMark rm(THREAD); int length; jchar* chars = symbol->as_unicode(length); Handle string; oop result = intern(string, chars, length, CHECK_NULL); return result;}
oop StringTable::intern(Handle string_or_null, jchar* name, int len, TRAPS) { unsigned int hashValue = hash_string(name, len); int index = the_table()->hash_to_index(hashValue); oop found_string = the_table()->lookup(index, name, len, hashValue); // Found if (found_string != NULL) { ensure_string_alive(found_string); return found_string; // 在the_table中找到字符串实例就返回 } debug_only(StableMemoryChecker smc(name, len * sizeof(name[0]))); assert(!Universe::heap()->is_in_reserved(name), "proposed name of symbol must be stable"); Handle string; // try to reuse the string if possible if (!string_or_null.is_null()) { string = string_or_null; } else { string = java_lang_String::create_from_unicode(name, len, CHECK_NULL); }#if INCLUDE_ALL_GCS if (G1StringDedup::is_enabled()) { // Deduplicate the string before it is interned. Note that we should never // deduplicate a string after it has been interned. Doing so will counteract // compiler optimizations done on e.g. interned string literals. G1StringDedup::deduplicate(string()); }#endif // Grab the StringTable_lock before getting the_table() because it could // change at safepoint. oop added_or_found; { MutexLocker ml(StringTable_lock, THREAD); // Otherwise, add to symbol to table added_or_found = the_table()->basic_add(index, string, name, len, hashValue, CHECK_NULL); } ensure_string_alive(added_or_found); return added_or_found;}
oop StringTable::basic_add(int index_arg, Handle string, jchar* name, int len, unsigned int hashValue_arg, TRAPS) { assert(java_lang_String::equals(string(), name, len), "string must be properly initialized"); // Cannot hit a safepoint in this function because the "this" pointer can move. No_Safepoint_Verifier nsv; // Check if the symbol table has been rehashed, if so, need to recalculate // the hash value and index before second lookup. unsigned int hashValue; int index; if (use_alternate_hashcode()) { hashValue = hash_string(name, len); index = hash_to_index(hashValue); } else { hashValue = hashValue_arg; index = index_arg; } // Since look-up was done lock-free, we need to check if another // thread beat us in the race to insert the symbol. oop test = lookup(index, name, len, hashValue); // calls lookup(u1*, int) if (test != NULL) { // Entry already added return test; } HashtableEntry* entry = new_entry(hashValue, string()); add_entry(index, entry); return string();}
openjdk8\openjdk\hotspot\src\share\vm\utilities\hashtable.hpp
templateclass HashtableEntry : public BasicHashtableEntry { friend class VMStructs;private: T _literal; // ref to item in table.public: // Literal T literal() const { return _literal; } T* literal_addr() { return &_literal; } void set_literal(T s) { _literal = s; } HashtableEntry* next() const { return (HashtableEntry*)BasicHashtableEntry ::next(); } HashtableEntry** next_addr() { return (HashtableEntry**)BasicHashtableEntry ::next_addr(); }};
templateinline void BasicHashtable ::add_entry(int index, BasicHashtableEntry * entry) { entry->set_next(bucket(index)); _buckets[index].set_entry(entry); ++_number_of_entries;}
转载地址:http://gkawb.baihongyu.com/