一.java內存區域java
jvm在執行java程序的過程當中會把所管理的內存分爲若干不一樣的區域,有的區域隨着虛擬機進程的啓動而存在,有些區域則是依賴用戶線程的啓動和結束而創建和銷燬的。算法
如下是java運行時內存區域圖:編程
1.程序計數器數組
程序計數器是一塊較小的區域,它能夠看作是當前所執行的字節碼的行號指示器。在java的多線程交互執行的過程當中,被中斷的線程當前執行到那條指令的內存地址須要被保存下來,以便於該中斷線程恢復執行的時候能夠按照被中斷時的指令繼續執行下去。安全
爲了能使每一個線程切換後都能恢復到正確的位置,所以每個線程都是須要有本身的程序計數器。每一個線程獨立存儲,互不影響,所以咱們成這個內存爲「線程私有」的內存。性能優化
2.java虛擬機棧多線程
每當建立一個線程,jvm就會爲該線程建立一個java虛擬機棧,虛擬機棧的生命週期與線程相同,它隨線程的建立與結束而啓動和銷燬的。該線程每調用一個方法,jvm就會在該虛擬機棧中建立一個棧幀,用於存放局部變量表,操做數棧,接口信息等。每個方法的從調用到完成的過程就對應一個棧幀在虛擬機棧中的入棧以及出棧的過程。正在執行的方法的棧幀位於棧頂。架構
虛擬機棧的這個內存區域爲"線程私有"的內存。併發
該區域可拋出兩種異常狀況:jvm
StackOverflowError異常:線程請求的棧的深度大於了虛擬機所容許的深度。
OutOfMemoryError異常:虛擬機棧東塔擴展時沒法申請到足夠長度。
3.本地方法棧
本地方法棧和Java棧所發揮的做用很是類似,區別不過是Java棧爲JVM執行Java方法服務,而本地方法棧爲JVM執行Native方法服務。 本地方法棧也會拋出StackOverflowError和OutOfMemoryError異常。
本地方法棧的這個內存區域爲"線程私有"的內存。
4.java堆
堆是JVM所管理的內存中國最大的一塊,是被全部Java線程鎖共享的,不是線程安全的,在JVM啓動時建立。堆是存儲Java對象的地方,這一點Java虛擬機規範中描述是:全部的對象實例以及數組都要在堆上分配。Java堆是GC管理的主要區域,從內存回收的角度來看,因爲如今GC基本都採用分代收集算法,因此Java堆還能夠細分爲:新生代和老年代;新生代再細緻一點有Eden空間、From Survivor空間、To Survivor空間等。
5.方法區
方法區用於存儲已被虛擬機加載的類信息,常量,靜態變量即編譯後的代碼以及數據。
在方法區中存在一部份內存稱爲「運行時常量區」,用於存放編譯器生成的各類字面量以及符號引用量。【其中,字面量就是指final變量等;引用變量包括類和接口的全限定名,字段名稱,方法名和描述符】
方法區爲java線程共享
當方法區沒法知足內存需求的時候,將拋出OutOfMemoryError異常。
二.java內存模型
2. Java內存模型規定了全部的變量都存儲在主內存中,每條線程還有本身的工做內存,線程的工做內存中保存了該線程中是用到的變量的主內存副本拷貝,線程對變量的全部操做都必須在工做內存中進行,而不能直接讀寫主內存。不一樣的線程之間也沒法直接訪問對方工做內存中的變量,線程間變量的傳遞均須要本身的工做內存和主存之間進行數據同步進行。
如:線程1 要與 線程2 進行數據交換,首先,線程1要把本身工做內存1中的數據更新保存到主內存中,而後線程2要去主內存中拷貝一份數據,刷新到本身的工做線程2之中。
3.java內存模型是圍繞着併發編程中的原子性,可見性,有序性這三個特徵來創建的。
原子性:一個操做要麼不執行,要麼所有執行完畢,不能被打斷。
可見性:一個線程對共享變量作了修改以後,其餘的線程當即可以看到該變量的變化。
有序性:在本線程內觀察,全部的操做都是無序的;若是在一個線程中觀察另外一個線程,全部的操做都是無序的。前半句是指「線程內表現爲串行語義」,後半句是指「指令重排」現象以及「工做內存與主內存同步延遲」現象。
4.總結:JMM是一種規範,目的是解決因爲多線程經過共享內存進行通訊時,存在的本地內存數據不一致、編譯器會對代碼指令重排序、處理器會對代碼亂序執行等帶來的問題。目的是保證併發編程場景中的原子性、可見性和有序性。
注:主內存和工做內存與JVM內存結構中的Java堆、棧、方法區等並非同一個層次的內存劃分,沒法直接類比。
在這裏順便給你們推薦一個架構交流羣: 956058372,裏面會分享一些資深架構師錄製的視頻錄像:有Spring,MyBatis,Netty源碼分析,高併發、高性能、分佈式、微服務架構的原理,JVM性能優化這些成爲架構師必備的知識體系。
![]()