這裏是修真院後端小課堂,每篇分享文從html
【背景介紹】【知識剖析】【常見問題】【解決方案】【編碼實戰】【擴展思考】【更多討論】【參考文獻】java
八個方面深度解析後端知識/技能,本篇分享的是:程序員
【jvm如何運行以及內存如何分配】算法
【修真院Java小課堂】jvm如何運行以及內存如何分配後端
開場語:數組
你們好,我是IT修真院北京分院第32期的學員廖友,一枚正直純潔善良的Java程序員,今天給你們分享一下,修真院官網Java任務拓展中的知識點——jvm如jvm
何運行以及內存如何分配工具
1、背景介紹:開發工具
jdk,jre,jvm的聯繫與區別優化
JDK:
是java開發工具包,是Sun公司針對java開發人員的產品,jdk中包含jre,在jdk的安裝目錄下有一個jre的目錄,裏面有兩個文件夾bin和lib,在這裏
能夠認爲bin裏面就是jvm,lib中是java工做須要的類庫,而java和lib合起來就稱爲jre
JRE:
是運行基於java語言編寫的程序所不可缺乏的運行環境,也是經過它,java的開發者才能夠將本身開發的程序發佈到用戶手中,讓用戶使用,與你們
熟悉的jdk不一樣,jre是運行環境,並非一個開發環境,因此沒有包含任何開發工具(如編譯器,調試器)等,知識針對使用java程序的用戶
JVM:
就是咱們常說的java虛擬機,它是整個java實現跨平臺的最核心的部分,全部的java程序首先被編譯爲.class文件,這種類文件能夠在虛擬機上運行
,也就是說class並不直接與機器的操做系統相對應。而是通過虛擬機間接的與操做系統交互,由虛擬機將程序解釋給本地系統執行,只有jvm還不能將class
執行,由於在解釋class的時候jvm須要調用解釋所須要的類庫lib,而jre包含lib類庫,jvm屏蔽了具體操做系統平臺的相關信息,使得java程序只須要生成
在java虛擬機上運行的目標代碼。能夠在多種平臺(操做系統)上不加修改的運行
JVM系統組成
類加載系統、執行引擎、運行時數據區
2、知識剖析:
一、程序計數器
程序計數器(Program Counter Register) 是一塊較小的內存空間,它能夠看做是當前線程所執行的字節碼的行號指示器。在虛擬機的概念模型裏,字節碼
解釋器工做時就是經過改變這個計數器的值來選取下一條執行字節碼指令。
每條線程都有一個獨立的程序計數器。
若是執行的是java方法,這個計數器記錄的是正在執行的虛擬機字節碼指令地址。若是是native方法,計數器爲空。
二、虛擬機棧
一樣是線程私有,描述Java方法執行的內存模型:每一個方法在執行的同時都會建立一個棧幀(Stack Frame)用於存儲局部變量表、操做數棧、動態連接、方
法出口等信息。一個方法對應一個棧幀。
局部變量表存放了各類基本類型、對象引用和returnAddress類型(指向了一條字節碼指令地址)。其中64位長度long 和 double佔兩個局部變量空間,其餘
只佔一個。
規定的異常狀況有兩種:1.線程請求的棧的深度大於虛擬機所容許的深度,將拋出StackOverflowError異常;2.若是虛擬機能夠動態擴展,若是擴展時沒法
申請到足夠的內存,就拋出OutOfMemoryError異常。
三、本地方法棧
和Java虛擬機棧很相似,不一樣的是本地方法棧爲Native方法服務。
四、Java堆
是Java虛擬機所管理的內存中最大的一塊。由全部線程共享,在虛擬機啓動時建立。堆區惟一目的就是存放對象實例。
堆中可細分爲新生代和老年代,再細分可分爲Eden空間、From Survivor空間、To Survivor空間。
堆沒法擴展時,拋出OutOfMemoryError異常
五、方法區
全部線程共享,存儲已被虛擬機加載的類信息、常量、靜態變量、即時編譯器編譯後的代碼等數據。
當方法區沒法知足內存分配需求時,拋出OutOfMemoryError
六、運行時常量池
它是方法區的一部分,Class文件中除了有類的版本、字段、方法、接口等描述信息外,還有一項是常量池(Const Pool Table),用於存放編譯期生成的各
種字面量和符號引用。並不是預置入Class文件中常量池的內容才進入方法運行時常量池,運行期間也可能將新的常量放入池中,這種特性被開發人員利用得比
較多的即是String類的intern()方法。
當方法區沒法知足內存分配需求時,拋出OutOfMemoryError
七、垃圾收集(GC)
7.1 哪些內存須要回收
在運行時區域中,程序計數器、虛擬機棧、本地方法棧3個區域隨線程而生,而線程而滅;棧中的棧幀隨着方法的進入和退出也有序的執行入棧出棧操做,且
棧幀的內存分配在編譯期就已經肯定了。所以這幾個區域的內存分配和回收都具有肯定性,在這幾個區域沒必要多考慮回收的問題,由於方法結束或者線程結
束時,內存天然就跟着回收了
須要進行GC操做的是方法區和堆,由於這部份內存是動態分配的,一個接口中的多個實現類須要的內存可能不同,一個方法中的多個分支須要的內存可能
也不同,咱們只有在程序處於運行期間時才能知道會建立哪些對象。
7.2 何時回收
引用計數算法:給對象中添加一個引用計數器,每當有引用它時,計數器值就加1;當引用失效時,計數器值就減1;任什麼時候刻計數器爲0的對象就是不可能再
被使用。
可達性分析算法:經過一系列的稱爲"GC Root"的對象做爲起點,從這些節點開始向下搜索,搜素所走過的路徑稱爲引用鏈(Reference Chain),當一個對
象到GC Root沒有任何的引用鏈相連,就斷定對象能夠被回收。
7.3 如何回收
垃圾收集算法:標記-清除算法、複製算法、標記-整理算法、分代整理算法
垃圾收集器:Serial收集器、ParNew收集器、Parallel Scavenge收集器、Parallel old、Serial old、CMS、GI
八、內存分配原則
對象優先分配到Eden區
大對象直接進入老年區(須要連續內存空間的對象,例如很長的字符串以及數組)
長期存活的對象將進入老年代(對象年齡計數器,每GC一次,age+1)
動態對象年齡綁定
空間分配擔保
3、編碼實戰
4、參考文獻:
1https://www.cnblogs.com/zhouy...
[2]《深刻理解Java虛擬機》
[3]http://www.importnew.com/1551...
5、更多討論:
Q1:有沒有能夠檢測jvm的工具
A1:檢測jvm的工具備不少,jdk本身就帶有不少個,如jps,jstart,jconsloe等,這些存放在bin目錄下
Q2:Java程序能夠運行在不一樣jvm中嗎?
A2:能夠的,好比安卓使用的是谷歌本身開發的davlik虛擬機,但咱們一樣能夠編寫Java程序在上面運行
Q3:jvm優化主要指那些方面
A3:最重要的就是堆的優化,由於這是存放對象的地方,是垃圾盛產地。
6、結束語:
今天的分享就到這裏啦,歡迎你們點贊、轉發、留言、拍磚~