CLRCore(CLR核心機制)

 

JIT--第一次--標記已--存根--調用--查找存根--執行機器碼程序員

 

 

C#和CIL的關係:數據庫

 

 C#和N#都是CIL實現,可是彼此不能互通:跨域

 

 C#和N#公開不分知足規範,咱們才能互通數據結構

 

 CLS就是描述多語言互通的規範函數

 

 

內存分配:線程棧優化

  堆Heap:this

    一個程序運行時,該進程存放引用類型變量的一塊內存,全局惟一!只有一個堆spa

  棧Stack:線程

    數據結構,先進後出,線程棧,一個線程存放變量的內存(一個線程有一個)3d

  值類型分配在棧上,好比結構、枚舉、int等

  引用類型分配在堆上,好比類、接口、委託等

引用類型

  一、調用new的時候,就會去棧上開闢內存,建立實例。這就是爲何在構造函數中跨域使用this

  二、把實例的引用傳遞給構造函數

  三、執行構造函數

  四、返回引用

裝箱拆箱

int i=3;
obect obj=i;//裝箱
int k=(int)obj;//拆箱

引用類型在哪裏?值類型在哪裏?

  值類型的值,會隨着對象的位置存儲。引用類型的值,必定在堆裏面。值類型的長度是肯定的,引用類型的長度是不肯定的,只有堆才能放各類值。

  下面有一個例子:

public class MyTest
{
    private int x;
    public MyTest(int n)
    {
        this.x=n;
    }
}
MyTest t=new MyTest(3);//引用類型

  那麼,t.x  這個3,是存放在哪裏呢?是堆上仍是棧上?

    ===.》出如今堆裏面,由於值類型的屬性,會隨着對象的位置存儲

 public struct ValuePoint// : System.ValueType  結構不能有父類,由於隱式繼承了ValueType
 {
     public int x;
     public ValuePoint(int x)
     {
         this.x = x;
         this.Text = "1234";
     }

     public string Text;//堆仍是棧?
 }

  struct是值類型,可是裏面的Text,是存放在堆仍是棧?答案是,對立面,由於引用類型的值,必定出如今堆裏面。

 

string字符串內存分配

string student = "bingle1";
string student2 = student;

Console.WriteLine(student);//bingle1
Console.WriteLine(student2);//bingle1

student2 = "bingle2";//=new string(APP);
Console.WriteLine(student);//bingle1
Console.WriteLine(student2);//bingle2
Console.ReadLine();
string student = "bingle1";
string student2 = "bingle2";//共享
student2 = "bingle1";

Console.WriteLine(object.ReferenceEquals(student, student2));//true

爲何是true?由於同一個變量,享元分配內存。爲何享元?節約內存。

student2 = "binglebingle";//等於從新開闢一塊內存叫「binglebingle」  new String("binglebingle")
Console.WriteLine(student);//bingle1

仍是bingle1,爲何?由於字符串的不可變性。爲何字符串不能夠變,開闢新內存不浪費嗎?由於在堆上是連續拜訪的,若是有變化,會致使其餘變量所有移動,成本過高,還不如從新new一個。

string student3 = string.Format("bing{0}", "le");
Console.WriteLine(object.ReferenceEquals(student, student3));//false

爲何是false?沒有享元。分配地址,而後計算,才知道是"bingle"。

 string student4 = "bing" + "le";
 Console.WriteLine(object.ReferenceEquals(student, student4));//true
 //true  編譯器優化了,直接就是bingle
string halfStudent = "le";
string student5= "bing" + halfStudent;
Console.WriteLine(object.ReferenceEquals(student, student5));
//false 也是先內存,再計算

東西放在站上速度快,可是值類型是不能繼承的,長度也有限。

垃圾回收---CLR提供GC,託管堆垃圾回收

  一、什麼樣的對象須要垃圾回收?

    託管資源+引用類型。線程棧的是不須要垃圾回收的,用完立馬就回收了。

  二、託管資源和非託管資源

    託管資源的就是CLR控制的,new的對象、string字符串。非託管就不是CLR控制的,數據庫鏈接、文件流、句柄、打印機鏈接。using(SqlConnection)//被C#封裝了管道了那個非託管的數據庫鏈接資源。只要手動釋放的,都是非託管的。

  三、哪些對象的內存,能被GC回收?

    對象訪問不到了,那就能夠被回收了。程序----入口----去找對象---創建對象圖----訪問不到的就是垃圾,就能夠回收了。

  四、對象是如何分配在堆上的?

    連續分配在堆上的,每次分配就先檢查空間夠不夠。

 

   五、何時執行GC?

    a、new對象的時候----臨界點

    b、GC.Collection(),這個方法會強制GC

    c、程序退出時會GC

    a="123"

    a=null

    GC.Collect 能夠GC,可是頻繁GC是很差的,GC是全局的

    項目中有6個小時才運行new一次,何時GC? 不GC,能夠手動GC

  六、GC的過程是怎麼樣的?

    N個對象,所有標機Wie垃圾,入口開始遍歷,訪問到的就標機能夠訪問(+1),遍歷完就清理內存,產生不連續的內存,壓縮,地址移動,修改變量指向,因此全局會阻塞。

    清理內存分兩種狀況:

      a、無析構函數,直接清理內存

      b、把對象轉到一個單獨的隊列,會有一個析構函數專門作這個。一般在析構函數內部是用來作非託管資源釋放,由於CLR確定調用,因此避免使用者忘記的氣礦。

  七、垃圾回收策略

 

     對象分代:3代

    0代:第一次分配到堆,就是0代

    1代:經歷了一次GC,還存在的

    2代:經歷了兩次或以上的GC,還存在的。

    垃圾回收時,優先回收0代,提高小路,最多也最容器釋放。0代不夠,找1代,1代不夠找2代,再不夠就不用了。。。代的數值越大,越難回收。

    大對象堆:一是內存移動大對象;二是0代空間問題。80000字節就叫大對象,沒有分代,直接都是2代。

    那麼,靜態資源在程序退出的時候,會GC嗎?答案是,會的。(其實回收的不是變量,是某個對象所佔據的內存,若是存在一個對象,指向它的引用變量的數量爲0,那個GC會擇機回收它佔據的內存。應用程序域卸載的時候回收靜態變量。)

 

析構函數:被動清理;Dispose:主動清理

    

 public class StandardDispose : IDisposable
 {
     //演示建立一個非託管資源
     private string _UnmanageResource = "未被託管的資源";
     //演示建立一個託管資源
     private string _ManageResource = "託管的資源";


     private bool _disposed = false;

     /// <summary>
     /// 實現IDisposable中的Dispose方法
     /// </summary>
     public void Dispose()
     {
         this.Dispose(true); //必須爲true
         GC.SuppressFinalize(this);//通知垃圾回收機制再也不調用終結器(析構器)
     }

     /// <summary>
     /// 不是必要的,提供一個Close方法僅僅是爲了更符合其餘語言(如C++)的規範
     /// </summary>
     public void Close()
     {
         this.Dispose();
     }

     /// <summary>
     /// 必須,以備程序員忘記了顯式調用Dispose方法
     /// </summary>
     ~StandardDispose()
     {
         //必須爲false
         this.Dispose(false);
     }

     /// <summary>
     /// 非密封類修飾用protected virtual
     /// 密封類修飾用private
     /// </summary>
     /// <param name="disposing"></param>
     protected virtual void Dispose(bool disposing)
     {
         if (this._disposed)//已經被釋放的還能夠不異常
         {
             return;
         }
         if (disposing)
         {
             // 清理託管資源
             if (this._ManageResource != null)
             {
                 //Dispose
                 this._ManageResource = null;
             }
         }
         // 清理非託管資源
         if (this._UnmanageResource != null)
         {
             //Dispose  conn.Dispose()
             this._UnmanageResource = null;
         }
         //讓類型知道本身已經被釋放
         this._disposed = true;
     }

     public void PublicMethod()
     {
         if (this._disposed)
         {
             throw new ObjectDisposedException("StandardDispose", "StandardDispose is disposed");
         }
         //
     }
相關文章
相關標籤/搜索