閱讀建議:本博客基於《Java編程思想》、《深刻理解Java虛擬機》、《java併發編程實戰》三本Java書籍和麪試中遇到的問題而作的總結。java
JVM(JAVA Virtual Machine Java虛擬機)運行時數據區域:程序計數器、虛擬機棧(爲執行Java方法服務)、本地方法棧(native方法服務)、堆(類實例)、方法區(類信息、常量、靜態變量,即時編譯器編譯的代碼),運行時常量池(用於存放編譯期生成的各類字面值和符號引用典型的有String類的intern())。面試
線程私有的區域:程序計數器、虛擬機棧、本地方法棧。編程
線程共享區域:堆、方法區、運行時常量池。數組
1、方法區安全
1.static變量:數據結構
在搞清楚靜態變量前,首先必須先清楚類實例和類對象的區別:類實例和類對象是不一樣的概念。從面向對象的角度出發,全部一切都是對象,類自己是對象的一種,類對象是個抽象的概念;類的實例就是具體類的實例對象,類實例是具體的概念;其次必須清楚編譯期(類的加載過程)與運行期JVM幹了哪些事。併發
靜態變量與類實例無關,屬於類對象的變量。靜態變量在類加載的時候就已經初始化值了,並存放在靜態存儲區中,在運行期直接經過類對象調用就行;非靜態變量須要new一個對象的實例,從對象實例中去獲取,他是存放於堆中(對象)或者堆棧中(基本類型)。性能
類的靜態變量只佔據一個存儲空間,全部對象實例都共享該對象類的靜態變量,也就是說全部new出來的對象實例,經過對象實例獲取的靜態字段的值都是取值同一個存儲空間的值。不會由於new一個對象實例而增長一塊存儲空間來存儲靜態變量,由於靜態變量在類加載的過程當中就已經分配存儲空間了,而且一次分配後就不再會從新分配新的存儲空間了。若是你經過不一樣的類實例去修改靜態變量的值,其餘其實獲取靜態變量的值就是已經改變後的值。spa
問題1:爲何調用static靜態變量不須要建立任何對象,直接經過類.靜態變量直接獲取?線程
2.final常量
2、運行常量池
1.String類型:String是final修飾的類,對象實例存在於運行時常量池或堆中。
a. 當調用 intern 方法時,若是池已經包含一個等於此 String 對象的字符串(該對象由 equals(Object) 方法肯定),則返回池中的字符串。不然,將此 String 對象添加到池中,而且返回此 String 對象的引用。
b.String a = "hello world"與 String a = new String("hello world")是不一樣的對象,前者存儲在運行時常量池,後者存放於堆中,兩者存在不一樣的運行時數據區域中;存放在常量池中的好處是節約內存空間,String a = "hello world",若是運行時常量池裏有這個字符串則句柄直接指向該字符串便可,若沒有則建立該字符串並將句柄a指向該字符串。
c.字符串爲什麼設計成final類型呢?從繼承、性能、併發安全上考慮。
4.基本數據類型:存放於堆棧中,便於高效存取。
5.數組
6.對象:
結合class文件結構以及類加載(加載、驗證、準備、解析、初始化、使用、卸載)過程詳細敘述以上變量的初始化過程,以及變量所在JVM運行時數據結構的位置。
說明:目前僅有提綱,後續會陸續補充