有意思的字串拘留實驗

weixin_34321977發表於2010-03-02

 本次字串拘留實驗分為4個,最終根據實驗得出了一個很有意思的結論。這些結論使兄弟們在以前關於字串操作的結論基礎上進行深入理解。(關於字串拘留池,請Google一下String Intern Pool,你可以搜尋到不少東西的。)

1 Main中沒有出現硬字串

            string a1 = new string('a', 1);

            string a2 = new string('a', 1);

            Console.WriteLine(a1);

            Console.WriteLine(string.IsInterned(a1) != null);

            Console.WriteLine(ReferenceEquals(a1, a2));

> a

> False

> False 

2 Main中出現硬字串

            string a1 = new string('a', 1);

            string a2 = new string('a', 1);

            Console.WriteLine(a1);

            Console.WriteLine(string.IsInterned(a1) != null);

            Console.WriteLine(string.IsInterned("a") != null);

            Console.WriteLine(ReferenceEquals(a1, a2));

> a

> True

> True

> False 

注意:為什麼第一個IsInterned竟然得出a已經拘留了呢?呵呵。

3 Main中不出現硬字串,但在另一個類出現硬字串,不過另一個類沒有被使用

            // a1 a2都不在拘留池,且地址不一樣。

            string a1 = new string('a', 1);

            string a2 = new string('a', 1);

            Console.WriteLine(a1);

            Console.WriteLine(string.IsInterned(a1) != null);

            Console.WriteLine(ReferenceEquals(a1, a2));

 

class StringInternPoolTest1

    {

        public StringInternPoolTest1()

        {

            string a1 = new string('a', 1);

            Console.WriteLine(string.IsInterned(a1) != null);

            string a = "a";

        }

}

> a

> False

> False 

4 Main中不出現硬字串,但使用了另一個具有硬字串的類

            string a1 = new string('a', 1);

            string a2 = new string('a', 1);

            Console.WriteLine(a1);

            Console.WriteLine(string.IsInterned(a1) != null);

            Console.WriteLine(ReferenceEquals(a1, a2));

            StringInternPoolTest1 test = new StringInternPoolTest1();

 

class StringInternPoolTest1

    {

        public StringInternPoolTest1()

        {

            string a1 = new string('a', 1);

            Console.WriteLine(string.IsInterned(a1) != null);

            string a = "a";

        }

}

> a

> False

> False

> True 

 

本次實驗結論:

1 只有硬字串才能被拘留;

2 JIT編譯方法後,執行前會將一個方法的所有硬字串拘留;

3 string x = "a" 不會執行記憶體分配,原因很簡單,在該語句之前JIT已經執行字串拘留,即JIT提前分配了字串的所需的記憶體以及字串拘留池項。

 

其它待實驗論點:

1 只有CLR執行結束,拘留字串才能被釋放;

2 拘留一個字串的行為為將引用新增到CLR的一個Hashtable,它始終對字串進行引用,從而阻止GC對拘留字串進行回收;

3 編譯器的優化行為(大家可以猜測一下如何優化,呵呵)。 

相關文章