OutOfMemoryError
,詳情見 【拒絕一問就懵】之不可忽視的內存泄露。程序計數器是線程私有的內存區域,這個區域是Java虛擬機中惟一一個沒有限制OutOfMemoryError
的內存區域。之因此須要它是由於Java的多線程機制是經過輪流切換分配處理器執行時間來實現的,因此會涉及到線程的暫停和重啓,而在一個線程中若是正在執行Java方法的話,這個計數器就回去記錄當前正在執行的虛擬機字節碼,一旦被暫停,恢復只須要從程序計數器記錄的爲止繼續執行就能夠。程序員
可是,若是線程中執行的是一個Native方法,那麼程序計數器是不會去記錄的,因此此時的程序計數器爲空。算法
Java虛擬機棧也是線程私有的。一條線程啓動就會爲它創建一個虛擬機棧。數組
在線程中每有一個Java方法被調用就會建立一個 「棧幀」 。每一個 「棧幀」 會保存執行該方法所需的局部變量表(通常Java程序員喜歡用這個部分來表明棧)、操做數棧、動態連接以及方法出口等信息。安全
若是一個線程中有過多的 「棧幀」 要入到虛擬機棧中,即短期內調用了過多的方法,就會形成 -- 棧益處 -- ,即 StackOverflowError 錯誤。bash
在這個內存區域中,若是虛擬機須要擴展內存,但沒有申請到足夠的內存,就會拋出 OutOfMemoryError 錯誤。多線程
和虛擬機棧有些相似,但它是爲Native方法提供服務的。併發
Java的堆內存是Java虛擬機所管理的內存中最大的一塊。它是全部線程所共享的,用於存放對象實例和數組,Java虛擬機的GC主要就發生在這個地方。所以這塊區域也叫作"GC堆"。工具
Java堆的內存能夠按照垃圾回收算法【分代回收】分爲【新生代區】和【老年區】,進一步的,【新生代區】能夠分爲【Eden區】、【From Survivor區】和【To Survivor區】。post
從內存角度來講,Java堆內存又被劃分爲線程共享的內存區域和每一個線程私有的內存區域。spa
在Java堆區域中,若是沒有內存分配給要建立的實例,而且堆也不可以再擴展,就會拋出OutOfMemoryError
錯誤。
在Java8以後,Heap Segment真正意義上的是由Young Generiation和Old Generiation組成的。對象在其中是標記複製算法來斷定一個對象是否應該被清理掉。
Heap Segment中發生的GC稱爲Major GC,只會影響Heap Segment區。
這個區域發生的GC稱爲Minor GC
。
-XX:MaxTenuringThreshold
該命令來調整閥值)時,這個對象將被複制到Old Generiation區中,此時該對象將會變的相對安全,由於Old Segment區的GC頻率相對較低。這個區域發送的GC成爲Full GC
。
OutOfMemoryError
。Java的方法區和Java的堆內存同樣是被線程所共有的。它主要存放虛擬機加載的類信息、常量、靜態變量、即時編譯產生的代碼等。
一些地方會將方法區合併到Java堆中一塊兒去說。把它做爲「永久代」。這在Hot-Spot虛擬機而言成立,可是通常來講是不成立的。
Java的方法區若是內存不夠分配的話,也是會拋出OutOfMemoryError
錯誤的。也就是若是加載過多類到方法區的話,可能會形成方法區內存益處。
在GC檢查對象的是否能夠回收時,是根據對象是否可到達引用練頂端的GC Roots
對象來判斷的。GC Roots
對象通常是虛擬機棧中變量表中引用的對象、類靜態屬性引用的對象、常量對象、JNI傳到底層的對象。就是說,一個對象若是溯源不到這幾種類型的對象的話,就認爲它是沒法到達的,那麼它將會在GC時被回收。
在JDK 1.2以後,Java擴充了4種引用類型定義:
即咱們平時經過new關鍵字建立出來的的對象的引用,只要強引用還存在,那麼這些對象就必定不回被回收,即便時拋出OutOfMemoryError
。何時強引用會不存在呢?當一個方法執行完,棧幀中的變量表將會被清理,在該方法中建立使用的臨時強引用就會被清理掉,以後,本來它指向的對象就被變的不可到達。
用來描述一些有用但不是必須的對象,即經過SoftReference
建立的對象,它們將會在本來肯定要發生內存溢出前的一次GC中被回收,若是回收完內存仍是不夠,Java堆就會拋出OutOfMemoryError
錯誤。就是說,在觸發內存溢出發生前,這些對象是和強引用同樣,只要引用還在,就不會被回收。
用來描述一些沒必要須的對象,即經過WeakReference
建立的對象。弱引用對象的生命週期只有一次GC。
一個對象的存在與否徹底不受虛引用的影響,它惟一的用處就是能夠用來監測一個對象是否被回收。
運行時常量池主要存放類中編譯時期生成的常量,固然也能夠動態的往裏面添加。
好比:
"abc".intern();
複製代碼
這個方法首先會檢查運行時常量池中是否有這個字符串,有的話取出來用,沒有的話生成一個並存到常量池中。
再好比,運行過程當中生成經過static
修飾的String時,也會加入到常量池中。對於String而言,常量 + 常量
生成的也是常量,可是常量 + 變量
生成的就是變量了。
Dalvik虛擬機是Google按照JVM虛擬機規範定製的虛擬機,它更符合移動設備的環境要求。與標準虛擬機不一樣:
.dex
文件,這種格式的文件體積更小。而JVM規範的是.class
文件。ART虛擬機在Android 5.0之後是被默認開啓的,此時Dalvik已經被Google放棄維護了。它與Dalvik虛擬機的不一樣:
看到這裏的童鞋快獎勵本身一口辣條吧!
想要看CoorChice更多的文章,能夠加個關注哦!