亚洲中字慕日产2020,大陆极品少妇内射AAAAAA,无码av大香线蕉伊人久久,久久精品国产亚洲av麻豆网站

資訊專欄INFORMATION COLUMN

JVM GC 之「AdaptiveSizePolicy」實(shí)戰(zhàn)

CoffeX / 3618人閱讀

摘要:如果開啟,則每次后會(huì)重新計(jì)算和區(qū)的大小,計(jì)算依據(jù)是過程中統(tǒng)計(jì)的時(shí)間吞吐量內(nèi)存占用量。應(yīng)用達(dá)到預(yù)期的吞吐量,即應(yīng)用正常運(yùn)行時(shí)間正常運(yùn)行時(shí)間耗時(shí)。理論上,增大內(nèi)存,可以降低的頻率,以此達(dá)到預(yù)期吞吐量。

轉(zhuǎn)載請注明原文鏈接:https://www.jianshu.com/p/741...
一、AdaptiveSizePolicy簡介

AdaptiveSizePolicy(自適應(yīng)大小策略) 是 JVM GC Ergonomics(自適應(yīng)調(diào)節(jié)策略) 的一部分。

如果開啟 AdaptiveSizePolicy,則每次 GC 后會(huì)重新計(jì)算 Eden、From 和 To 區(qū)的大小,計(jì)算依據(jù)是 GC 過程中統(tǒng)計(jì)的 GC 時(shí)間、吞吐量、內(nèi)存占用量。

開啟 AdaptiveSizePolicy 的參數(shù)為:

-XX:+UseAdaptiveSizePolicy

JDK 1.8 默認(rèn)使用 UseParallelGC 垃圾回收器,該垃圾回收器默認(rèn)啟動(dòng)了 AdaptiveSizePolicy。

AdaptiveSizePolicy 有三個(gè)目標(biāo):

Pause goal:應(yīng)用達(dá)到預(yù)期的 GC 暫停時(shí)間。

Throughput goal:應(yīng)用達(dá)到預(yù)期的吞吐量,即應(yīng)用正常運(yùn)行時(shí)間 / (正常運(yùn)行時(shí)間 + GC 耗時(shí))。

Minimum footprint:盡可能小的內(nèi)存占用量。

AdaptiveSizePolicy 為了達(dá)到三個(gè)預(yù)期目標(biāo),涉及以下操作:

如果 GC 停頓時(shí)間超過了預(yù)期值,會(huì)減小內(nèi)存大小。理論上,減小內(nèi)存,可以減少垃圾標(biāo)記等操作的耗時(shí),以此達(dá)到預(yù)期停頓時(shí)間。

如果應(yīng)用吞吐量小于預(yù)期,會(huì)增加內(nèi)存大小。理論上,增大內(nèi)存,可以降低 GC 的頻率,以此達(dá)到預(yù)期吞吐量。

如果應(yīng)用達(dá)到了前兩個(gè)目標(biāo),則嘗試減小內(nèi)存,以減少內(nèi)存消耗。

注:AdaptiveSizePolicy 涉及的內(nèi)容比較廣,本文主要關(guān)注 AdaptiveSizePolicy 對年輕代大小的影響,以及隨之產(chǎn)生的問題。

AdaptiveSizePolicy 看上去很智能,但有時(shí)它也很調(diào)皮,會(huì)引發(fā) GC 問題。

二、由 AdaptiveSizePolicy 引發(fā)的 GC 問題

某一天,有一位群友在群里發(fā)來一張 jmap -heap 內(nèi)存使用情況圖。

說 Survivor 區(qū)占比總是在 98% 以上。

仔細(xì)觀察這張圖,其中包含幾個(gè)重要信息:

From 和 To 區(qū)都比較小,只有 10M。容量比較小,才顯得占比高。

Old 區(qū)的占比和使用量(兩個(gè)多 G)都比較高。

此外,還可以看到 Eden、From、To 之間的比例不是默認(rèn)的 8:1:1。

于是,立馬就想到 AdaptiveSizePolicy。

經(jīng)群友的確認(rèn),使用的是 JDK 1.8 的默認(rèn)回收算法。

JVM 參數(shù)配置如下:

參數(shù)中沒有對 GC 算法進(jìn)行配置,即使用默認(rèn)的 UseParallelGC。

用默認(rèn)參數(shù)啟動(dòng)一個(gè)基于 JDK 1.8 的應(yīng)用,然后使用 jinfo -flags pid 即可查看默認(rèn)配置的 GC 算法。

上文提到,該算法默認(rèn)開啟 AdaptiveSizePolicy。

即使 SurvivorRatio 的默認(rèn)值是 8,但年輕代三個(gè)區(qū)域之間的比例仍會(huì)變動(dòng)。

這個(gè)問題,可以參考來自R大的回答:

http://hllvm.group.iteye.com/...

HotSpot VM里,ParallelScavenge系的GC(UseParallelGC / UseParallelOldGC)默認(rèn)行為是SurvivorRatio如果不顯式設(shè)置就沒啥用。顯式設(shè)置到跟默認(rèn)值一樣的值則會(huì)有效果。

因?yàn)镻arallelScavenge系的GC最初設(shè)計(jì)就是默認(rèn)打開AdaptiveSizePolicy的,它會(huì)自動(dòng)、自適應(yīng)的調(diào)整各種參數(shù)。

在群友的截圖中,F(xiàn)rom 區(qū)只有 10M,Eden 區(qū)占用了卻超過年輕代八成的空間。

其原因是 AdaptiveSizePolicy 為了達(dá)到期望的目標(biāo)而進(jìn)行了調(diào)整。

大概定位了 Survivor 區(qū)小的原因,還有一個(gè)問題:

為什么老年代的占比和使用量都比較高?

于是群友使用 jmap -histo 查看堆中的實(shí)例。

可以看出,其中有兩個(gè)類的實(shí)例比較多,分別是:

LinkedHashMap$Entry

ExpiringCache$Entry

于是,搜索關(guān)鍵類 ExpiringCache。

可以看出在 ExpiringCache 的構(gòu)造函數(shù)中,初始化了一個(gè) LinkedHashMap。

懷疑 LinkedHashMap$Entry 數(shù)量多的原因和 ExpiringCache$Entry 直接有關(guān)。

ExpiringCache(long millisUntilExpiration) {
    this.millisUntilExpiration = millisUntilExpiration;
    map = new LinkedHashMap() {
        protected boolean removeEldestEntry(Map.Entry eldest) {
          return size() > MAX_ENTRIES;
        }
      };
}

注:該 map 用于保存緩存數(shù)據(jù),設(shè)置了淘汰機(jī)制。當(dāng) map 大小超過 MAX_ENTRIES = 200 時(shí),會(huì)開始淘汰。

接著查看 ExpiringCache$Entry 類。

這個(gè)類的主要屬性是「時(shí)間戳」和「值」,時(shí)間戳用于超時(shí)淘汰(緩存常用手法)。

static class Entry {
    private long   timestamp;
    private String val;
    ……
}

接著查看哪里使用到了這個(gè)緩存。

于是找到 get 方法,定位到只有一個(gè)類的一個(gè)方法使用到了這個(gè)緩存。

接著往上層找,看到了一個(gè)熟悉的類:File,它的 getCanonicalPath() 方法使用到了這個(gè)緩存。

該方法用于獲取文件路徑。

于是,詢問群友,是否在項(xiàng)目中使用了 getCanonicalPath() 方法。

得到的回答是肯定的。

當(dāng)項(xiàng)目中使用 getCanonicalPath() 方法獲取文件路徑時(shí),會(huì)發(fā)生以下的事情:

首先從緩存中讀取,取不到則需要生成緩存。

生成緩存需要新建 ExpiringCache$Entry 對象用于保存緩存值,這些新建的對象都會(huì)被分配到 Eden 區(qū)。

當(dāng)大量使用 getCanonicalPath() 方法時(shí),緩存數(shù)量超過 MAX_ENTRIES = 200 開啟淘汰策略。原來 map 中的 ExpiringCache$Entry 對象變成垃圾對象,真正存活的 Entry 只有 200 個(gè)。

當(dāng)發(fā)生 YGC 時(shí),理論上存活的 200 個(gè) Entry 會(huì)去往 To 區(qū),其他被淘汰的垃圾 Entry 對象會(huì)被回收。

但由于 AdaptiveSizePolicy 將 To 區(qū)調(diào)整到只有 10MB,裝不下本該移動(dòng)到 To 區(qū)的對象,只能直接移動(dòng)到老年代

于是,在每次 YGC 時(shí),會(huì)有接近 200 個(gè)存活的 ExpiringCache$Entry 對象進(jìn)入到老年代。隨著緩存淘汰機(jī)制的運(yùn)行,這些 Entry 對象立馬又變成垃圾。

當(dāng)對象進(jìn)入老年代,即使變成了垃圾,也需要等到老年代 GC 或者 FGC 才能將其回收。由于老年代容量較大,可以承受多次 YGC 給予的 200 個(gè) ExpiringCache$Entry 對象。

于是,老年代使用量逐漸變高。

老年代內(nèi)存占用量高的問題也定位到了。

因?yàn)槊看?YGC 只有 200 個(gè)實(shí)例進(jìn)入到老年代,問題顯得比較溫和。

只是隔一段時(shí)間觸發(fā) FGC,應(yīng)用運(yùn)行看似正常。

接著使用 jstat -gcutil 查看 GC 情況。

可以看到從應(yīng)用啟動(dòng),一共發(fā)生了 15654 次 YGC。

推算每次 YGC 有 200 個(gè) ExpiringCache$Entry 對象進(jìn)入老年代。

那么,老年代中大約存在 3130800 個(gè) ExpiringCache$Entry 對象。

從之前的 jmap -histo 結(jié)果中看到,ExpiringCache$Entry 對象的數(shù)量是 6118824 個(gè)。

兩個(gè)數(shù)目都為百萬級。其余約 300W 個(gè)實(shí)例應(yīng)該都在 Eden 區(qū)。

每一次 YGC 后,都會(huì)有大量的 ExpiringCache$Entry 對象被回收。

從群友截取的 GC log 中可以看出,YGC 的頻率大概為 23 秒一次。

假設(shè)運(yùn)行的 jmap -histo 命令是在即將觸發(fā) YGC 之前。

那么,應(yīng)用大概在 20s 的事件內(nèi)產(chǎn)生了 300W 個(gè) ExpiringCache$Entry 實(shí)例,1s 內(nèi)產(chǎn)生約 15W 個(gè)。

假設(shè)單機(jī) QPS = 300,一次請求產(chǎn)生的 ExpiringCache$Entry 實(shí)例數(shù)約為 500 個(gè)。

猜測是在循環(huán)體中使用了 getCanonicalPath() 方法。

至此可以得出 Survior 區(qū)變小,老年代占比變高的原因:

在默認(rèn) SurvivorRatio = 8 的情況下,沒有達(dá)到吞吐量的期望,AdaptiveSizePolicy 加大了 Eden 區(qū)的大小。From 和To 區(qū)被壓縮到只有 10M。

在項(xiàng)目中大量使用 getCanonicalPath() 方法,產(chǎn)生大量ExpiringCache$Entry 實(shí)例。

當(dāng) YGC 發(fā)生時(shí)候,由于 To 區(qū)太小,存活的 Entry 對象直接進(jìn)入到老年代。老年代占用量逐漸變大。

從群友的 jstat -gcutil 截圖中還可以看出,應(yīng)用從啟動(dòng)到使用該命令,觸發(fā)了 19 次 FGC,一共耗時(shí) 9.933s,平均每次 FGC 耗時(shí)為 520ms。

這樣的停頓時(shí)間,對于一個(gè)高 QPS 的應(yīng)用是無法忍受的。

定位到了問題的原因,解決方案比較簡單。

解決的思路有兩個(gè):

不使用緩存,就不會(huì)生成大量 ExpiringCache$Entry 實(shí)例。

阻止 AdaptiveSizePolicy 縮小 To 區(qū)。讓 YGC 時(shí)存活的 ExpiringCache$Entry 對象都能順利進(jìn)入 To 區(qū),保留在年輕代,而不是進(jìn)入老年代。

解決方案一:

不使用緩存。

使用 -Dsun.io.useCanonCaches = false 參數(shù)即可關(guān)閉緩存。

這種方案解決比較方便,但這個(gè)參數(shù)并非常規(guī)參數(shù),慎用。

解決方案二:

保持使用 UseParallelGC,顯式設(shè)置 -XX:SurvivorRatio=8。

配置參數(shù)進(jìn)行測試:

看到默認(rèn)配置下,三者之間的比例不是 8:1:1。

可以看到,加上參數(shù) -Xmn100m -XX:SurvivorRatio=8 參數(shù)后,固定了 Eden 和 Survivor 之間的比例。

解決方案三:

使用 CMS 垃圾回收器。

CMS 默認(rèn)關(guān)閉 AdaptiveSizePolicy。

配置參數(shù) -XX:+UseConcMarkSweepGC,通過 jinfo 命令查看,可以看到 CMS 默認(rèn)減去/不使用 AdaptiveSizePolicy。

群友也是采用了這個(gè)方法:

可以看出,Eden 和 Survivor 之間的比例被固定,To 區(qū)沒有被縮小。老年代的使用量和使用率也都很正常。

三、源碼層面了解 AdaptiveSizePolicy

注:以下源碼均主要基于 openjdk 8,不同 jdk 版本之間會(huì)有區(qū)別。

對源碼的理解程度有限,對源碼的理解也一直在路上。

有任何錯(cuò)誤,還請各位指正,謝謝。

首先解釋,為什么在 UseParallelGC 回收器的前提下,顯式配置 SurvivorRatio 即可固定年輕代三個(gè)區(qū)域之間的比例。

在 arguments.cpp 類中有一個(gè) set_parallel_gc_flags() 方法。

從方法命名來看,是為了設(shè)置并行回收器的參數(shù)。

// If InitialSurvivorRatio or MinSurvivorRatio were not specified, but the
  // SurvivorRatio has been set, reset their default values to SurvivorRatio +
  // 2.  By doing this we make SurvivorRatio also work for Parallel Scavenger.
  // See CR 6362902 for details.
  if (!FLAG_IS_DEFAULT(SurvivorRatio)) {
    if (FLAG_IS_DEFAULT(InitialSurvivorRatio)) {
       FLAG_SET_DEFAULT(InitialSurvivorRatio, SurvivorRatio + 2);
    }
    if (FLAG_IS_DEFAULT(MinSurvivorRatio)) {
      FLAG_SET_DEFAULT(MinSurvivorRatio, SurvivorRatio + 2);
    }
  }

當(dāng)顯式設(shè)置 SurvivorRatio,即 !FLAG_IS_DEFAULT(SurvivorRatio),該方法會(huì)設(shè)置別的參數(shù)。

方法注釋上寫著:

make SurvivorRatio also work for Parallel Scavenger
通過顯式設(shè)置 SurvivorRatio 參數(shù),SurvivorRatio 就會(huì)在 Parallel Scavenge 回收器中生效。

至于為何會(huì)生效,還有待進(jìn)一步學(xué)習(xí)。

而默認(rèn)是會(huì)被 AdaptiveSizePolicy 調(diào)整的。

接著查看 AdaptiveSizePolicy 動(dòng)態(tài)調(diào)整內(nèi)存大小的代碼。

JDK 1.8 默認(rèn)的 UseParallelGC 回收器,其對應(yīng)的年輕代回收算法是 Parallel Scavenge。

觸發(fā) GC 的原因有多種,最普通的一種是在年輕代分配內(nèi)存失敗。

UseParallelGC 分配內(nèi)存失敗引發(fā) GC 的入口位于
vmPSOperations.cpp 類的 VM_ParallelGCFailedAllocation::doit() 方法。

之后依次調(diào)用了以下方法:

parallelScavengeHeap.cpp 類的 failed_mem_allocate(size_t size) 方法。

psScavenge.cpp 類的 invoke()、invoke_no_policy() 方法。

invoke_no_policy() 方法中有一段代碼涉及 AdaptiveSizePolicy。

if (UseAdaptiveSizePolicy) {
  ……
  size_policy->compute_eden_space_size(young_live,
                                               eden_live,
                                               cur_eden,
                                               max_eden_size,
                                               false /* not full gc*/);
  ……
}

在 GC 主過程完成后,如果開啟 UseAdaptiveSizePolicy 則會(huì)重新計(jì)算 Eden 區(qū)的大小。

在 compute_eden_space_size 方法中,有幾個(gè)判斷。

對應(yīng) AdaptiveSizePolicy 的三個(gè)目標(biāo):

與預(yù)期 GC 停頓時(shí)間對比。

與預(yù)期吞吐量對比。

如果達(dá)到預(yù)期,則調(diào)整內(nèi)存容量。

if ((_avg_minor_pause->padded_average() > gc_pause_goal_sec()) ||
      (_avg_major_pause->padded_average() > gc_pause_goal_sec())) {
    adjust_eden_for_pause_time(is_full_gc, &desired_promo_size, &desired_eden_size);
  } else if (_avg_minor_pause->padded_average() > gc_minor_pause_goal_sec()) {
    adjust_eden_for_minor_pause_time(is_full_gc, &desired_eden_size);
  } else if(adjusted_mutator_cost() < _throughput_goal) {
    assert(major_cost >= 0.0, "major cost is < 0.0");
    assert(minor_cost >= 0.0, "minor cost is < 0.0");
    adjust_eden_for_throughput(is_full_gc, &desired_eden_size);
  } else {
    if (UseAdaptiveSizePolicyFootprintGoal &&
        young_gen_policy_is_ready() &&
        avg_major_gc_cost()->average() >= 0.0 &&
        avg_minor_gc_cost()->average() >= 0.0) {
      size_t desired_sum = desired_eden_size + desired_promo_size;
      desired_eden_size = adjust_eden_for_footprint(desired_eden_size, desired_sum);
    }
  }

詳細(xì)看其中一個(gè)判斷。

if ((_avg_minor_pause->padded_average() > gc_pause_goal_sec()) ||
      (_avg_major_pause->padded_average() > gc_pause_goal_sec()))

如果統(tǒng)計(jì)的 YGC 或者 Old GC 時(shí)間超過了目標(biāo)停頓時(shí)間,則會(huì)調(diào)用 adjust_eden_for_pause_time 調(diào)整 Eden 區(qū)大小。

gc_pause_goal_sec() 方法獲取預(yù)期停頓時(shí)間,在 ParallelScavengeHeap::initialize() 方法中,通過讀取 JVM 參數(shù) MaxGCPauseMillis 獲取。

接下來,再看 CMS 回收器。

CMS 初始化分代位于 cmsCollectorPolicy.cpp 類的 initialize_generations() 方法。

if (UseParNewGC) {
  if (UseAdaptiveSizePolicy) {
    _generations[0] = new GenerationSpec(Generation::ASParNew,
                                         _initial_gen0_size, _max_gen0_size);
  } else {
    _generations[0] = new GenerationSpec(Generation::ParNew,
                                         _initial_gen0_size, _max_gen0_size);
  }
} else {
  _generations[0] = new GenerationSpec(Generation::DefNew,
                                       _initial_gen0_size, _max_gen0_size);
}
if (UseAdaptiveSizePolicy) {
  _generations[1] = new GenerationSpec(Generation::ASConcurrentMarkSweep,
                          _initial_gen1_size, _max_gen1_size);
} else {
  _generations[1] = new GenerationSpec(Generation::ConcurrentMarkSweep,
                          _initial_gen1_size, _max_gen1_size);
}

其中 _generations[0] 代表年輕代特征,_generations[1] 代表老年代特征。

如果設(shè)置不同的 UseParNewGC 、UseAdaptiveSizePolicy 參數(shù),會(huì)對年輕代和老年代使用不同的策略。

CMS 垃圾回收入口位于 genCollectedHeap.cpp 類的 do_collection 方法。

在 do_collection 方法中,GC 主過程完成后,會(huì)對每個(gè)分代進(jìn)行大小調(diào)整。

for (int j = max_level_collected; j >= 0; j -= 1) {
  // Adjust generation sizes.
  _gens[j]->compute_new_size();
}

本文主要討論 AdaptiveSizePolicy 對年輕代的影響,主要看 ASParNewGeneration 類,其中的 AS 前綴就是 AdaptiveSizePolicy 的意思。

如果設(shè)置 -XX:+UseAdaptiveSizePolicy 則年輕代對應(yīng) ASParNewGeneration 類,否則對應(yīng) ParNewGeneration 類。

在 ASParNewGeneration 類中 compute_new_size() 方法中,調(diào)用了另一個(gè)方法調(diào)整 Eden 區(qū)大小。

size_policy->compute_eden_space_size(eden()->capacity(), max_gen_size());

該方法與 Parallel Scavenge 的 compute_eden_space_size 方法類似,也從三個(gè)方面對內(nèi)存大小進(jìn)行調(diào)整,分別是:

adjust_eden_for_pause_time

adjust_eden_for_throughput

adjust_eden_for_footprint

接著進(jìn)行測試,設(shè)置參數(shù) -XX:+UseAdaptiveSizePolicy、
-XX:+UseConcMarkSweepGC。

期望 CMS 會(huì)啟用 AdaptiveSizePolicy,但根據(jù) jmap -heap 結(jié)果查看,并沒有啟動(dòng),年輕代三個(gè)區(qū)域之間的比例為 8:1:1。

從 jinfo 命令結(jié)果也可以看出,即使設(shè)置了 -XX:+UseAdaptiveSizePolicy,仍然關(guān)閉了 AdaptiveSizePolicy。

因?yàn)樵?JDK 1.8 中,如果使用 CMS,無論 UseAdaptiveSizePolicy 如何設(shè)置,都會(huì)將 UseAdaptiveSizePolicy 設(shè)置為 false。

查看 arguments.cpp 類中的 set_cms_and_parnew_gc_flags 方法,其調(diào)用了 disable_adaptive_size_policy 方法將 UseAdaptiveSizePolicy 設(shè)置成 false。

static void disable_adaptive_size_policy(const char* collector_name) {
  if (UseAdaptiveSizePolicy) {
    if (FLAG_IS_CMDLINE(UseAdaptiveSizePolicy)) {
      warning("disabling UseAdaptiveSizePolicy; it is incompatible with %s.",
              collector_name);
    }
    FLAG_SET_DEFAULT(UseAdaptiveSizePolicy, false);
  }
}

如果是在啟動(dòng)參數(shù)中設(shè)置了,則會(huì)打出提醒。

但在 JDK 1.6 和 1.7 中,set_cms_and_parnew_gc_flags 方法的邏輯和 1.8 中的不同。

如果 UseAdaptiveSizePolicy 參數(shù)是默認(rèn)的,則強(qiáng)制設(shè)置成 false。

如果顯式設(shè)置(complete),則不做改變。

// Turn off AdaptiveSizePolicy by default for cms until it is
// complete.
if (FLAG_IS_DEFAULT(UseAdaptiveSizePolicy)) {
  FLAG_SET_DEFAULT(UseAdaptiveSizePolicy, false);
}

于是嘗試使用 JDK 1.6 搭建 web 應(yīng)用,加上 -XX:+UseAdaptiveSizePolicy、-XX:+UseConcMarkSweepGC 兩個(gè)參數(shù)。

再用 jinfo -flag 查看,看到兩個(gè)參數(shù)都被置為 true。

接著,使用 jmap -heap 查看堆內(nèi)存使用情況,發(fā)現(xiàn)展示不了信息。

這其實(shí)是 JDK 低版本的一個(gè) Bug。

1.6.30以上到1.7的全部版本已經(jīng)確認(rèn)有該問題,jdk8修復(fù)。

參考:UseAdaptiveSizePolicy與CMS垃圾回收同時(shí)使用導(dǎo)致的JVM報(bào)錯(cuò) https://www.cnblogs.com/moona...

四、問題小結(jié)

現(xiàn)階段大多數(shù)應(yīng)用使用 JDK 1.8,其默認(rèn)回收器是 Parallel Scavenge,并且默認(rèn)開啟了 AdaptiveSizePolicy。

AdaptiveSizePolicy 動(dòng)態(tài)調(diào)整 Eden、Survivor 區(qū)的大小,存在將 Survivor 區(qū)調(diào)小的可能。當(dāng) Survivor 區(qū)被調(diào)小后,部分 YGC 后存活的對象直接進(jìn)入老年代。老年代占用量逐漸上升從而觸發(fā) FGC,導(dǎo)致較長時(shí)間的 STW。

建議使用 CMS 垃圾回收器,默認(rèn)關(guān)閉 AdaptiveSizePolicy。

建議在 JVM 參數(shù)中加上 -XX:+PrintGCDetails -XX:+PrintGCDateStamps -XX:+PrintHeapAtGC -XX:+PrintTenuringDistribution,讓 GC log 更加詳細(xì),方便定位問題。

五、參考資料

Garbage Collector Ergonomics

File,file.getPath(), getAbsolutePath(), getCanonicalPath()區(qū)別

UseAdaptiveSizePolicy與CMS垃圾回收同時(shí)使用導(dǎo)致的JVM報(bào)錯(cuò)

JVM分析工具概述

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://www.ezyhdfw.cn/yun/77153.html

相關(guān)文章

  • [譯]GC專家系列4-Apache的MaxClients設(shè)置及其對Tomcat Full GC的影響

    摘要:本文將介紹的參數(shù)的重要性以及在發(fā)生時(shí)對系統(tǒng)整體性能的顯著影響。我們來看下的選項(xiàng)在發(fā)生時(shí)會(huì)對系統(tǒng)帶來哪些影響。所以這些請求將會(huì)放到堆積隊(duì)列,隊(duì)列的長度是的中設(shè)置的。從而導(dǎo)致進(jìn)程的數(shù)量超過,并觸發(fā)了操作系統(tǒng)進(jìn)行內(nèi)存交換的閥值。 原文鏈接:http://www.cubrid.org/blog/dev-platform/maxclients-in-apache-and-its-effect-o...

    DangoSky 評論0 收藏0
  • 一次有趣的局部變量GC

    摘要:前言最近在看實(shí)戰(zhàn)虛擬機(jī)發(fā)現(xiàn)書上的一個(gè)關(guān)于局部變量表挺有意思,先上代碼。主角沒有分配了一塊的堆空間,并使用局部變量引用這塊空間然后顯式進(jìn)行一次。 前言 最近在看《實(shí)戰(zhàn)Java虛擬機(jī)》, 發(fā)現(xiàn)書上的一個(gè)關(guān)于局部變量表GC挺有意思,先上代碼。 主角 沒有GC public class Main { public static void reversion(){ { ...

    alogy 評論0 收藏0
  • 學(xué)習(xí)JVM必看書籍

    學(xué)習(xí)JVM的相關(guān)資料 《深入理解Java虛擬機(jī)——JVM高級特性與最佳實(shí)踐(第2版)》 showImg(https://segmentfault.com/img/bVbsqF5?w=200&h=200); 基于最新JDK1.7,圍繞內(nèi)存管理、執(zhí)行子系統(tǒng)、程序編譯與優(yōu)化、高效并發(fā)等核心主題對JVM進(jìn)行全面而深入的分析,深刻揭示JVM的工作原理。以實(shí)踐為導(dǎo)向,通過大量與實(shí)際生產(chǎn)環(huán)境相結(jié)合的案例展示了解...

    shaonbean 評論0 收藏0
  • Docker 監(jiān)控實(shí)戰(zhàn)

    摘要:監(jiān)控告警是運(yùn)營系統(tǒng)最核心的功能之一,騰訊內(nèi)部有一套很成熟的監(jiān)控告警平臺(tái),而且開發(fā)運(yùn)維同學(xué)已經(jīng)習(xí)慣這套平臺(tái),如果我們針對容器再開發(fā)一個(gè)監(jiān)控告警平臺(tái),會(huì)花費(fèi)很多精力,而且沒有太大的意義。也是一款付費(fèi)監(jiān)控解決方案,計(jì)劃收費(fèi)方案是美分小時(shí)。 如今,越來越多的公司開始使用 Docker 了,現(xiàn)在來給大家看幾組數(shù)據(jù): 2 / 3 的公司在嘗試了 Docker 后最終使用了它 也就是說 Docker...

    william 評論0 收藏0

發(fā)表評論

0條評論

閱讀需要支付1元查看
<