做用:加載Class文件java
1.虛擬機自帶的加載器 2.啓動類加載器 3.擴展類加載器 4.應用程序加載器算法
雙親委派機制:編程
類加載器收到類加載的請求,將這個請求向上委託給父類加載器,一直向上委託jvm
啓動加載器檢查是否能加載當前這個類,能加載就結束,使用當前加載器,不然拋出異常,通知子加載器進行加載編程語言
字節碼校驗器:確保java類文件遵循語言規範。工具
類裝載器:1.防止惡意代碼去幹涉代碼;雙親委派機制2.守護了被信任的類庫邊界3.將代碼納入保護域,肯定了代碼能進行什麼操做spa
凡是帶了native關鍵字的,說明java的做用範圍達不到了,回去調用底層的c語言的庫線程
進入本地方法棧,調用本地方法接口JNI對象
JNI:擴展java的使用,融合不一樣的編程語言爲java所用blog
Native Method Stack:登記native方法,在最終執行的時候經過JNI調用本地方法庫
程序計數器(Program Counter Register)是一塊較小的內存空間,它能夠看做是當前線程所執行的字節
碼的行號指示器。在虛擬機的概念模型裏(僅是概念模型,各類虛擬機可能會經過一些更高效的方式去實現)
字節碼解釋器工做時就是經過改變這個計數器的值來選取下一條須要執行的字節碼指令,分支、循環跳轉、
異常處理、線程恢復等基礎功能都須要依賴這個計數器賴完成。
方法區是被全部線程共享的,全部的字段和方法字節碼以及一些特殊的方法,都在此定義,次區域屬於共享區間。
靜態變量、常量、類信息、運行時的常量池存在方法區中,實例變量存在堆內存中,和方法區無關
Jdk1.8以後被元空間所代替
Heap,一個jvm只有一個堆內存,堆內存的大小是能夠調節的
堆中主要存放的就是實例化後的數據,類,方法,常量,變量,全部引用類型的真實對象
三個區域
類所實例化的對象:誕生、成長、死亡的地方
伊甸園區:全部的對象都是在這new出來的,若是這裏滿了就會產生一次輕量級GC,倖存者會存到新生區中的倖存區 eden
倖存0區 from或to
倖存1區 to或from 誰空誰是to
當倖存區滿了後會觸發重量級GC,活下來的會存到養老區(默認一個對象經歷了15次GC)
常駐內存區域,存放jdk自身攜帶的class對象,存儲的是java運行時的一些環境或類信息,這個區域不存在垃圾回收,關閉虛擬機就會釋放這個區域的內存
jdk1.6以前:永久代,常量池在方法區中
jdk1.7 :永久代,可是慢慢退化了,去永久代,常量池在堆中
jdk1.8以後:無永久代,常量池在元空間
邏輯上存在,物理上不存在
1.嘗試擴大堆內存看結果
-Xms1024m -Xmx1024m -XX:+PrintGCDetails
2.分析內存,看下哪一個地方出現了問題
使用Jprofiler工具
-Xms1m -Xmx8m -XX:+HeapDumpOnOutofMemoryError
引用計數法:須要給每一個對象分配一個計數器,計算使用次數,計數器也須要消耗內存(jvm不採用)
Survivor區,一塊叫From,一塊叫To,對象存在Eden和From塊。當進行GC時,Eden存活的對象全移到To塊,而From中,存活的對象按年齡值肯定去向,當達到必定值(年齡閾值,經過-XX:MaxTenuringThreshold可設置)的對象會移到年老代中,沒有達到值的複製到To區,通過GC後,Eden和From被清空。
以後,From和To交換角色,新的From即爲原來的To塊,新的To塊即爲原來的From塊,且新的To塊中對象年齡加1
沒有內存碎片但多了一半空間永遠是空的to(爲了保證可以複製到一個地方),而且存在極端狀況所有存活的時候須要所有複製
掃描對象:對對象進行標記
清除:對沒有標記的對象進行清除
兩次掃描嚴重浪費時間會產生內存碎片,不須要額外的空間
壓縮:防止內存碎片,再次掃描,向一端移動存活的對象,多了移動成本