這次記錄內容主要內容包括如下三塊內容: html
內存模型和結構; java
垃圾回收機制; 算法
類加載機制; bash
一,Java內存模型與JVM內存結構 微信
JVM內存模型與內存結構是兩個大相徑庭的東西,你們都知道Java內存分爲堆和棧,被問到內存相關都會這樣回答,可是今天要弄清楚什麼是內存模型什麼是內存結構?多線程
JVM內存模型簡稱(JMM)是一種抽象的概念,並非像JVM內存結構同樣是實際存在的,而是由於Java的多線程之間是經過共享內存進行通訊的,而因爲採用共享內存進行通訊,在通訊過程當中會存在一系列如可見性、原子性、順序性等問題,而JMM就是圍繞着多線程通訊以及與其相關的一系列特性而設計創建出來的的模型。oracle
目的是解決因爲多線程經過共享內存進行通訊時候,存在本地內存數據不一致,,編譯器對代碼重排序,以及處理器對代碼亂序執行帶來的問題,從而保證Java程序在各類平臺下對內存的訪問都能保證效果的一致性。 jvm
JVM內存結構是一種實際存在的結構體,由Java虛擬機規範定義,是Java程序執行過程當中,由JVM管理的不一樣數據區域,而且各個區域有其特定的功能。學習
二,JVM垃圾回收機制 spa
Java語言通常狀況下不須要開發人員本身去處理內存問題,自己存在垃圾回收機制,那麼Java的垃圾回收機制究竟是什麼?
在說明垃圾回收機制以前先說一下Java中的內存溢出以及內存泄漏的是怎麼回事?
內存溢出:out of memory,是指在程序申請內存時候,沒有足夠的空間可供提供,好比加載一個大型遊戲出現內存不足,再簡單一點就是在僅僅只有Integer大小的空間內放置Long大小的數據,那麼就會形成內存溢出。
內存泄漏:memory leak,是指程序申請到了內存,可是程序沒有在不須要內存空間時候即便釋放,形成內存空間只會一直減小,這種行爲被稱爲內存泄露,內存泄漏一次沒有關係,可是屢次的內存泄漏積累的結果必定會形成內存不足。
好的咱們開始從如下幾點進行逐步瞭解Java主流虛擬機hotspot的垃圾回收機制,其餘類型的虛擬機感興趣的能夠去作更深刻了解。
1,什麼是垃圾?
沒有被引用的對象在Java中就被稱爲垃圾
2,怎麼判斷垃圾?
判斷一個對象是否成爲垃圾有如下幾種方式
引用計數法 :
爲對象添加一個引用計數器,當對象增長一個引用時計數器就加1,引用失效計數器就減1,當引用技術爲0時對象可被回收。不過,當兩個對象出現循環引用時,兩個對象的引用計數器永遠不會爲0,這樣會致使他們沒法被回收。
引用可達法
以 GC Roots 爲起始點進行搜索,可達的對象都是存活的,不可達的對象可被回收。
GCRoot通常爲如下幾種:
方法區回收
方法區存的通常就是永久代(年老代)對象,回收起來比年輕代要更加困難,因此對方法區的回收條件更加嚴格,主要也是對常量池的回收和類的卸載,知足如下條件纔有可能被回收,可是也不必定會被回收。
該類全部的實例都已經被回收;
此時堆中不存在該類的任何實例;
加載該類的 ClassLoader 已經被回收 ;
該類對應的 Class 對象沒有在任何地方被引用,也就沒法在任何地方經過反射訪問該類方法。
finalize()
finalize()是Object的方法,存在的意義看似是,當類複寫了finalize()方法,能夠在對象被回收以前只調一次,來達到所謂的完成最後的功能,可是即便調用了,也不能保證方法會所有執行,可能會在方法執行過程當中被回收
3,垃圾怎麼回收 ?
標記清除算法
分爲兩個階段,先標記出來要回收的區域,而後贊成進行清除。
存在問題:
1,內存不連續,空間碎片太多
2,標記和清除效率低
複製算法(新生代)
將可用內存分爲兩等份,每次使用其中一份,進行垃圾回收的時候將,存活對象複製到另外一塊沒有使用的可用空間上面,而後把使用過的內存空間一次性所有清理。
優勢:簡單高效,內存連續
不足:內存利用不充分,當對象存活率廣泛較高時,因爲內存只是用一半,須要屢次執行。
標記整理算法(老年代)
標記整理,與上面的標記清理相似,只是標記整理不是將被標記的進行清除,而是將存活對象移動到一塊兒,將剩餘外界的進行清理。
分代收集算法
Java會把Java堆區域分爲新生和年老代,而後根據不一樣的年代進行不一樣算法的回收。
新生代:大批會被回收,只有少許會繼續存活,因此複製算法更加合適。
老年代:被回收的概率較低,因此適合標記整理,標記清除算法。
4,Java不一樣類型的引用
強引用:
Object obj = new Object()
複製代碼
廣泛存在的引用,只要引用還在就永遠不會被回收。
軟引用:
軟引用用來描述一些還有用可是非必須的對象,系統在將要發生內存溢出以前,將會把這些對象列進回收範圍,並進行第二次回收,若是將弱引用對象及進行回收以後依然沒有足夠的內存,那麼會拋出內存異常。
弱引用 :
非必須對象的引用,強度要比軟引用更弱,被弱引用指向的對象只能生存到下一次垃圾回收以前。當垃圾回收器工做時候,不管內存是否足夠,都會回收掉被弱引用指向的對象。
虛引用 :
虛引用存在不存在沒有太大意義,僅僅是爲了這個被虛引用指向的對象在被垃圾回收器回收的時候收到一個系統通知。
三,類加載機制
什麼是類加載機制?
Class文件中的各類信息,都是須要加載到虛擬機中才能運行,虛擬機把描述類的數據從Class文件加載到內存,並對數據進行校驗,轉換解析和初始化,最終造成能夠被虛擬機使用的Java類型,這就是Java虛擬機的類加載機制。
類加載過程:加載-->驗證-->準備-->解析-->初始化-->使用-->卸載
雙親委派模型是什麼?
雙親委派模型(Parents Delegation Model)要求除了頂層的啓動類加載器,其他加載器都應當有本身的父類加載器,類加載器之間經過組合關係複用。 雙親委派模型工做過程:若是一個類加載器收到類加載請求,他不會本身去加載這個類,而是請求給父類加載器去完成,每一個層次的加載器都是如此,所以全部的加載任務都會傳到頂層的啓動加載類,只有在父類反饋沒法完成加載任務的時候,纔會由子類本身去完成加載工做。
爲何要有雙親委派模型?
採用雙親委派模型使得Java類隨着它的類加載器一塊兒具有了一種帶有優先級的層次關係。例如類java.lang.Object,它存放在rt.jar中,不管哪一個類加載器要加載這個類,最終都會委派給啓動類加載器進行加載,所以Object類在程序的各類類加載器環境中都是同一個類。相反,若是用戶本身寫了一個名爲java.lang.Object的類,並放在程序的Classpath中,那系統中將會出現多個不一樣的Object類,java類型體系中最基礎的行爲也沒法保證,應用程序也會變得一片混亂。
記錄這些也是記錄本身學習過程,因此若是您發現不足或者錯誤之處,敬請雅正、不捨賜教。
若是你也正在學習或者複習中不妨關注微信公衆號:【Java成長錄】一塊兒學習。
參考文獻:
https://www.hollischuang.com/archives/2509)
https://docs.oracle.com/javase/specs/jvms/se8/html/jvms-2.html#jvms-2.5(Java虛擬機規範)
周志明. 深刻理解 Java 虛擬機 [M]. 機械工業出版社, 2011.