解釋內存中的棧(stack)、堆(heap)和方法區(method area) 的用法?


通常我們定義一個基本數據類型的變量,一個對象的引用,還有就是函數調用的

現場保存都使用 JVM 中的棧空間;而通過 new 關鍵字和構造器創建的對象則放在

堆空間,堆是垃圾收集器管理的主要區域,由於現在的垃圾收集器都采用分代收

集算法,所以堆空間還可以細分為新生代和老生代,再具體一點可以分為 Eden、

Survivor(又可分為 From Survivor 和 To Survivor)、Tenured;方法區和堆都

是各個線程共享的內存區域,用於存儲已經被 JVM 加載的類信息、常量、靜態變

量、JIT 編譯器編譯后的代碼等數據;程序中的字面量(literal)如直接書寫的 100、”

hello”和常量都是放在常量池中,常量池是方法區的一部分,。棧空間操作起來

最快但是棧很小,通常大量的對象都是放在堆空間,棧和堆的大小都可以通過 JVM

的啟動參數來進行調整,棧空間用光了會引發 StackOverflowError,而堆和常量

池空間不足則會引發 OutOfMemoryError。

String str = new String("hello");

上面的語句中變量 str 放在棧上,用 new 創建出來的字符串對象放在堆上,而”

hello”這個字面量是放在方法區的。

補充 1:較新版本的 Java(從 Java 6 的某個更新開始)中,由於 JIT 編譯器的發

展和”逃逸分析”技術的逐漸成熟,棧上分配、標量替換等優化技術使得對象一

定分配在堆上這件事情已經變得不那么絕對了。

補充 2:運行時常量池相當於 Class 文件常量池具有動態性,Java 語言並不要求

常量一定只有編譯期間才能產生,運行期間也可以將新的常量放入池中,String

類的 intern()方法就是這樣的。

看看下面代碼的執行結果是什么並且比較一下 Java 7 以前和以后的運行結果是否

一致。

String s1 = new StringBuilder("go")

.append("od").toString();

System.out.println(s1.intern() == s1);

String s2 = new StringBuilder("ja")

.append("va").toString();

System.out.println(s2.intern() == s2);


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM