1. 程式人生 > >JVM垃圾收集(Java Garbage Collection / Java GC)

JVM垃圾收集(Java Garbage Collection / Java GC)

ati www. tpc oid getjson com 分配 The tof

JVM垃圾收集(Java Garbage Collection / Java GC)

Java7

技術分享圖片

Java8

JDK1.8之後將最初的永久代取消了,由元空間取代。

技術分享圖片

堆內存調優簡介

技術分享圖片

public static void main(String[] args){
	//返回 Java 虛擬機試圖使用的最大內存量。
	long maxMemory = Runtime.getRuntime().maxMemory() ;
	//返回 Java 虛擬機中的內存總量。
	long totalMemory = Runtime.getRuntime().totalMemory() ;
	System.out.println("MAX_MEMORY = " + maxMemory + "(字節)、" + (maxMemory / (double)1024 / 1024) + "MB");
	System.out.println("TOTAL_MEMORY = " + totalMemory + "(字節)、" + (totalMemory / (double)1024 / 1024) + "MB");
}

發現默認的情況下分配的內存是總內存的“1 / 4”、而初始化的內存為“1 / 64”。

技術分享圖片

VM參數:-Xms1024m -Xmx1024m -XX:+PrintGCDetails

技術分享圖片

技術分享圖片

IntelliJ IDEA 的設置 技術分享圖片

技術分享圖片

String str = "www.baidu.com" ;
while(true){
	str += str + new Random().nextInt(88888888) + new Random().nextInt(999999999) ;
}

VM參數:-Xms8m -Xmx8m -XX:+PrintGCDetails

技術分享圖片 技術分享圖片

官網訪問地址:

public static async Task<JObject> GetJsonAsync(Uri uri)
{
using (var client = new HttpClient(www.yongshiyule178.com))
{
var jsonString = await client.GetStringAsync(uri);
return JObject.Parse(jsonString);
}
}

// 頂層調用方法
public void Button1_Click(...)
{
var jsonTask = GetJsonAsync(www.huarenyl.cn...);

textBox1.Text = jsonTask.Result;
}
復制代碼
  ASP.NET例子:API Action發起遠程HTTP請求,等待請求的json結果,並解析json字符串,以下代碼也會引發deadlock
復制代碼
public static async Task<JObject> GetJsonAsync(Uri uri)
{
using (var client = new HttpClient())
{
var jsonString = await client.GetStringAsync(uri);
return JObject.Parse(jsonString);
}
}
// My "top-level"www.taoyyunsheng.com method.
public class MyController : ApiController
{
public string Get()
{
var jsonTask = GetJsonAsync(www.honglanggjpt.cn...);
return jsonTask.Result.ToString();
}
}
復制代碼

   解決以上deadlock需利用以上第②③條編程原則:
不要混合使用異步、同步代碼,始終使用async/await語法糖編寫異步代碼

在等待的異步任務內應用ConfigureAwait(false)方法 (:不再嘗試從捕獲的同步上下文執行異步編程的後續代碼)

   第②③條原則與我們今天的主角SynchronizationContext 密切相關,大多數時候SynchronizationContext 是在異步編程後面默默工作的, 但是了解這個對象對於理解Task、await/sync 工作原理大有裨益。本文會解釋
為什麽要有SynchronizationContext 對象

闡述await關鍵字與SynchronizationContext對象交互原理

以上代碼為什麽會有deadlock, 另外ASP.NET Core為什麽不會發生以上死鎖


1. The Need for SynchronizationContext
  先看下MSDN中關於SynchronizationContext的定義:
提供在各種同步模型中傳播同步上下文的基本功能。此類實現的同步模型的目的是允許公共語言運行庫的內部異步/同步操作使用不同的同步模型正常運行。
  上面的定義給我的印象是:在線程切換過程中保存前置線程執行的上下文環境。

  我們大家都知道:Windows Form和WPF都基於類似的原則: 不允許在非UI線程上操作 UI元素

  
  這個時候我們可以捕獲當前執行環境SynchronizationContext,利用這個對象切換回原UI線程。

復制代碼
public static void DoWork()
{
//On UI thread
var sc = SynchronizationContext.Current;

ThreadPool.QueueUserWorkItem( www.365soke.com delegate
{
// do work on ThreadPool
sc.Post(delegate
{
// do work on the original context (UI)
}, null);
});
}
復制代碼
SynchronizationContext表示代碼正在運行的當前環境,每個線程都有自己的SynchronizationContext,通過SynchronizationContext.Current可獲取當前線程的同步上下文。利用該對象,可在線程池線程B執行完成後,嘗試切換到原調用線程A執行特定代碼。

2. await/async語法糖與SynchronizationContext 的關系?
  以上ThreadPool.QueueUserWorkItem 涉及線程底層,微軟提出Task線程包裝類和 await/async 簡化了異步編程的方式:

  
  ① 調用異步方法GetStringAsync時,.NET框架為我們創建了異步任務T;
  ② 應用await時,框架捕獲當前環境, 存儲在SynchronizationContext 對象並附加於以上Task;

  ③ 同時,控制權返回到原上層調用函數,返回一個未完成的Task<int>對象,這個時候需要關註上層調用函數使用 await異步等待還是使用Result/Wait()方式同步等待

  ④ 異步任務T執行完成,await之後的代碼將會成為continuation block, 默認情況下利用捕獲的SynchronizationContext 對象執行該continuation block 代碼。

    內部實際是將continuation block代碼放入 SynchronizationContext 的Post方法。

    不同的.NET框架因各自獨特的需求 有不同的 Post實現(Post是一個虛方法):

- 默認的SynchronizationContext.Post實現是將 委托通過QueueUserWorkItem傳遞給 ThreadPool。

- Windows Form有WindowsFormSynchronizationContext, Post方法將委托傳遞給 Control.BeginInvoke

- WPF 有DispatcherSynchronizationContext , Post方法將委托傳遞給 Dispatcher.BeginInvoke


3.引言代碼為什麽發生deadlock, 而ASP.NET Core為什麽不會發生類似deadlock?
仔細觀察引言代碼,控制返回到 上層調用函數時, 該調用函數使用Result屬性去等待任務結果,Result/Wait()等同步方式會導致調用線程掛起等待任務完成。而在異步方法內部,await觸發的異步任務執行完成後,會嘗試利用捕獲的同步上下文執行剩余代碼,而該同步上下文中的線程正同步等待整個異步任務完成,形成死鎖。

正因為如此,我們提出:

  - 在原調用函數始終 使用 await方法,這樣該線程是異步等待 任務完成。

  - 在異步任務內部應用ConfigureAwait(false)方法:

MSDN ConfigureAwait(www.dfgjpt.com): true to attempt www.gouyiflb.cn/ to marshal the continuation back to the original context captured; otherwise, false
  另外註意:ASP.NET Core不存在SynchronizationContext , 故不會發生類似的死鎖。


總結:
  雖然await/async 語法糖讓我們在編寫.NET 異步程序時得心應手、隨心所欲,但是不要忘記了SynchronizationContext 在其中轉承起合的作用。

利用能夠保存當前執行代碼的上下文特性,SynchronizationContext在線程切換後幫我們有能力執行各種騷操作。

技術分享圖片

技術分享圖片

-XX:+HeapDumpOnOutOfMemoryError OOM時導出堆到文件。

-Xms1m -Xmx8m -XX:+HeapDumpOnOutOfMemoryError

技術分享圖片

JVM垃圾收集(Java Garbage Collection / Java GC)