国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 學院 > 開發設計 > 正文

Eclipse 的字符串分區共享優化機制

2019-11-18 15:13:04
字體:
來源:轉載
供稿:網友

  在 java/C# 這樣基于引用語義處理字符串的語言中,作為不可變對象存在的字符串,假如內容相同,則可以通過某種機制實現重用。因為對這類語言來說,指向內存中兩塊內存位置不同內容相同的字符串,與同時指向一個字符串并沒有任何區別。非凡是對大量使用字符串的 xml 文件解析類似場合,這樣的優化能夠很大程度上降低程序的內存占用,如 SAX 解析引擎標準中就專門定義了一個 http://xml.org/sax/features/string-interning 特性用于字符串重用。

  在語言層面,Java/C# 中都直接提供了 String.Intern 的支持。而對 Java 來說,實現上的非常類似。由 String.intern 方法,將當前字符串以內容為鍵,對象引用為值,放入一個全局性的哈希表中。

  代碼:

//
// java/lang/String.java
//

public final class String
{
 //...
 public native String intern(); // 使用 JNI 函數實現以保障效率
}

//
// hotspot/src/share/vm/PRims/jvm.cpp
//

JVM_ENTRY(jstring, JVM_InternString(JNIEnv *env, jstring str))
JVMWrapper("JVM_InternString");
if (str == NULL) return NULL;
 oop string = JNIHandles::resolve_non_null(str); // 將引用解析為內部句柄
 oop result = StringTable::intern(string, CHECK_0); // 進行實際的字符串 intern 操作
 return (jstring) JNIHandles::make_local(env, result); // 獲取內部句柄的引用
 JVM_END
 //
 // hotspot/src/share/vm/memory/symbolTable.cpp
 //
 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); // 獲取實際字符串內容
  oop result = intern(h_string, chars, length, CHECK_0); // 完成字符串 intern 操作
  return result;
 }
 oop StringTable::intern(Handle string_or_null, jchar* name, int len, TRAPS)
 {
  int hashValue = hash_string(name, len); // 首先根據字符串內容計算哈希值
  stringTableBUCket* bucket = bucketFor(hashValue); // 根據哈希值獲取目標容器
  oop string = bucket->lookup(name, len); // 然后檢測字符串是否已經存在
  // Found
  if (string != NULL) return string;
  // Otherwise, add to symbol to table
  return basic_add(string_or_null, name, len, hashValue, CHECK_0); // 將字符串放入哈希表
 }
  對全局字符串表中的字符串,是沒有辦法顯式手動清除的。只能在不使用此字符串后,由垃圾回收線程在進行不可達對象標記時進行分析,并最終調用 StringTable::unlink 方法去遍歷清除。

  代碼:

//
// hotspot/src/share/vm/memory/genMarkSweep.cpp
//

void GenMarkSweep::mark_sweep_phase1(...)
{
 //...
 StringTable::unlink();
}

//
// hotspot/src/share/vm/memory/symbolTable.cpp
//

void StringTable::unlink() {
 // Readers of the string table are unlocked, so we should only be
 // removing entries at a safepoint.
 assert(SafepointSynchronize::is_at_safepoint(), "must be at safepoint")
 for (stringTableBucket* bucket = firstBucket(); bucket <= lastBucket(); bucket++) {
  for (stringTableEntry** p = bucket->entry_addr(); *p != NULL;) {
   stringTableEntry* entry = *p;
   assert(entry->literal_string() != NULL, "just checking");
   if (entry->literal_string()->is_gc_marked()) { // 字符串對象是否可達
    // Is this one of calls those necessary only for verification? (DLD)
    entry->oops_do(&MarkSweep::follow_root_closure);
    p = entry->next_addr();
   } else { // 如不可達則將其內存塊回收到內存池中
    *p = entry->next();
    entry->set_next(free_list);
    free_list = entry;
   }
  }
 }
}
  通過上面的代碼,我們可以直觀了解到,對 JVM (Sun JDK 1.4.2) 來說,String.intern 提供的是全局性的基于哈希表的共享支持。這樣的實現雖然簡單,并能夠在最大限度上進行字符串共享;但同時也存在共享粒度太大,優化效果無法度量,大量字符串可能導致全局字符串表性能降低等問題。

  為此 Eclipse 舍棄了 JVM 一級的字符串共享優化機制,而通過提供細粒度、完全可控、可測量的字符串分區共享優化機制,一定程度上緩解此問題。Eclipse 核心的 IStringPoolParticipant 接口由使用者顯式實現,在其 shareStrings 方法中提交需要共享的字符串。

  代碼:



發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 桃园市| 河南省| 娱乐| 南宁市| 荔浦县| 峨眉山市| 即墨市| 庆安县| 扎囊县| 郧西县| 南充市| 麦盖提县| 富阳市| 新田县| 鹰潭市| 霸州市| 嘉义市| 白银市| 资阳市| 庆云县| 乌拉特中旗| 固安县| 乌拉特中旗| 兴仁县| 宝兴县| 漯河市| 库尔勒市| 阳城县| 富宁县| 巴里| 宁强县| 河南省| 桂林市| 蛟河市| 定日县| 平舆县| 洛南县| 将乐县| 玉溪市| 白沙| 偏关县|