hotspot 源码下载
hotspot下载链接:http://hg.openjdk.java.net/jdk8u/jdk8u/hotspot/archive/tip.tar.gz
或者指定某个版本:http://hg.openjdk.java.net/jdk8u/jdk8u/hotspot/archive/1c0a59cee0e4.tar.gz
源码查看
解压下载的文件,使用vscode打开解压后的目录,按vscode提示安装C/C++ for Visual Studio Code插件。
jdk 源码下载
jdk8u下载链接:http://hg.openjdk.java.net/jdk8u/jdk8u/jdk/archive/tip.tar.gz
java native 方法查看
在vscode中打开上面下载的jdk8u源代码,如 Java String#intern()方法的源码即为share/native/java/lang目录下的Java_java_lang_String_intern。
JNIEXPORT jobject JNICALLJava_java_lang_String_intern(JNIEnv *env, jobject this){ return JVM_InternString(env, this);} |
在openjdk/hotspot/src/share/vm/prims/jvm.cpp文件第4058行,找到JVM_InternString方法定义如下:
4058405940604061406240634064406540664067 | // String support ///////////////////////////////////////////////////////////////////////////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 |
上面代码中的StringTable::intern()方法是关键代码,这个方法定义在openjdk/hotspot/src/share/vm/classfile/symbolTable.cpp第730行,代码如下:
730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829 | oop StringTable::lookup(jchar* name, int len) { unsigned int hash = hash_string(name, len); int index = the_table()->hash_to_index(hash); oop string = the_table()->lookup(index, name, len, hash); ensure_string_alive(string); return string;}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; } 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 (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()); } // 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::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(oop string, TRAPS){ if (string == NULL) return NULL; ResourceMark rm(THREAD); int length; Handle h_string (THREAD, string); jchar* chars = java_lang_String::as_unicode_string(string, length, CHECK_NULL); oop result = intern(h_string, chars, length, CHECK_NULL); return result;}oop StringTable::intern(const char* utf8_string, TRAPS) { if (utf8_string == NULL) return NULL; ResourceMark rm(THREAD); int length = UTF8::unicode_length(utf8_string); jchar* chars = NEW_RESOURCE_ARRAY(jchar, length); UTF8::convert_to_unicode(utf8_string, chars, length); Handle string; oop result = intern(string, chars, length, CHECK_NULL); return result;}void StringTable::unlink_or_oops_do(BoolObjectClosure* is_alive, OopClosure* f, int* processed, int* removed) { BucketUnlinkContext context; buckets_unlink_or_oops_do(is_alive, f, 0, the_table()->table_size(), &context); _the_table->bulk_free_entries(&context); *processed = context._num_processed; *removed = context._num_removed;} |