線程共享指的就是可以允許被所有線程共享訪問的一塊內存,包括堆區(qū),方法區(qū)和運行時常量池。
-
java堆區(qū)
java堆區(qū)在虛擬機啟動時被創(chuàng)建,并且他在實際內存中是可以不連續(xù)的。java堆區(qū)是用于存儲對象實例的一塊內存,同時也是垃圾回收器執(zhí)行的重點區(qū)域,因為堆區(qū)是垃圾回收器的重點回收區(qū)域,所以gc極有可能會在大內存的使用和回收工作上稱為性能瓶頸。為了解決這個問題,JVM考慮是否一定會將對象的實例存儲到java堆區(qū)內。
基于OpenJDK,深度定制的TaoBaoVM,其中創(chuàng)新的GCIH技術實現(xiàn)將生命周期較長的對象從堆區(qū)移動到堆外,并且垃圾回收器不可以處理這塊內存,以此降低垃圾回收器的回收頻率和提升垃圾回收器的目的。在某些特殊的應用中有許多很大的對象而且生命周期也很長,那么他們的存在必定會給垃圾回收器造成很多不必要的工作負擔。假設淘寶有許多大量的重復對象,據(jù)說對象超多數(shù)百MB。他們本身在應用提供服務前創(chuàng)建,在服務過程中永遠存在,那么實際垃圾回收器對這塊內存做的收集就沒用,如果我們將這些對象移動到堆外那么他們之前占據(jù)的堆就會不用那么每次FULLGC時間就會減少,GCIH為在jvm間共享對象提供了必要的基礎。通過該技術可以實現(xiàn)對象的共享,從而減少了內存的總體占用量。除此之外,逃逸分析與棧上分配等優(yōu)化技術也是降低了垃圾回收器,這樣一來java堆區(qū)不在是java對象分配的唯一地方了。
存儲在jvm中的java對象可以劃分為兩類,一類是生命周期較短的對象,該類對象創(chuàng)建和消亡非常快速,相反另外的一類對象生命周期非常長,在某些極端情況下可能和虛擬機生命周期一樣長,因此對于這些不同的對象應該采取不同的回收方法。目前所有的垃圾回收都是采用分代算法,所以在堆區(qū)應該在劃分為新生代和老年代,新生代又分為Eden 和 FROM Survivor和To Survivor。既然java堆區(qū)用于存儲java對象的實例,那么堆的大小在虛擬機啟動時就設定好啦,可以通過Xms設置最小堆區(qū) Xmx最大堆區(qū)。一旦堆區(qū)的內存大小超多最大堆區(qū)會拋出OutOfMemoryError
2,方法區(qū)
方法區(qū)和堆區(qū)一樣是允許被所有線程共享訪問,方法區(qū)存儲了每一個java類的結構信息,比如運行時常量池,字段和方法數(shù)據(jù),構造函數(shù)和普通方法的字節(jié)碼內容以及類,實例,接口初始化時需要的特殊方法等數(shù)據(jù),盡管虛擬機規(guī)范對方法區(qū)的具體實現(xiàn)的方法并沒有就具體說明但是在HotSpot中,方法區(qū)僅僅只是邏輯上的獨立,實際還是被包含在java堆區(qū)內,也就是說物理上屬于java堆區(qū)的一部分。
方法區(qū)在虛擬機啟動時被創(chuàng)建,并且它的實際的內存空間和java堆區(qū)一樣可以是不連續(xù)的。方法區(qū)是一塊比較特殊的運行時內存區(qū),有一些開發(fā)人員更愿意將方法區(qū)稱為永久區(qū),這是主要因為方法區(qū)除了可以通多選項-XX MaxPermSize設置內存大小進行動態(tài)擴除外,并不會像java堆區(qū)那樣頻繁的被gc執(zhí)行回收,設置還可以顯式的制定是否需要在程序運行時回收方法區(qū)中的數(shù)據(jù)。如果沒有顯式要求不對方法區(qū)內存回收的情況,gc的回收目標僅針對方法區(qū)中的常量池信息和類型卸載。方法區(qū)也可能出現(xiàn)OutOfMemoryError。條件是出現(xiàn)內存大小超多-XX MaxPermSize
3.運行時常量池屬于方法區(qū)的一部分,也可能OutOfMemoryError。
線程私有內存
1.pc寄存器
由于虛擬機是基于棧的結構,所有任何的操作都需要入棧和出棧,虛擬機的pc寄存器并非廣義的物理寄存器,應該是pc寄存器,pc寄存器是對物理pc寄存器的一種抽象模擬,他是線程私有的,生命周期與線程的生命周期一樣,
如果當前線程所執(zhí)行的是一個java方法,那么寄存器機會存儲正在執(zhí)行的字節(jié)碼指令地址,反之如果是本地方法那么就是指向null,就是寄存器值是空未定義。
寄存器為什么設計為線程私有?
我們知道所謂的多線程在一個指定的時間段里只會執(zhí)行某一個線程的方法,CPU不停切換任務,那么為了能夠準備的記錄各個線程正在執(zhí)行的當前的字節(jié)碼指令的地址,那么就設計為線程私有每個線程都分配一個寄存器,這樣各個線程獨自記錄不會干擾。這是java虛擬機唯一一個沒有聲明OutOfMemoryError的內存區(qū)。
2.java棧
在虛擬機規(guī)范中,線程私有,生命周期與線程的生命周期一樣.用于存儲棧幀,而棧幀就是存著局部變量表,操作數(shù)棧,以及方法出口信息等.
java堆區(qū)既然存在的是對象實例,那么棧區(qū)中的局部變量表就是用于存儲個類原始數(shù)據(jù)類型,對象引用,以及返回類型.如果遞歸深度過深會拋出OutOfMemoryError
3,本地方法棧
這塊用c++實現(xiàn)