JVM主要的功能:html
內存分配java
程序調度數據庫
內存釋放(棧等自動釋放、堆垃圾回收)編程
異常處理數據結構
http://www.javashuo.com/article/p-poxahysy-cd.html函數
https://blog.csdn.net/CSDN_980979768/article/details/47281037?locationNum=7&fps=1性能
Java程序生命週期操作系統
.java(程序源代碼)--編譯器-->.class(字節碼)--類裝載器-->StartApp(Main)--JVM(解釋器+即時編譯器)-->程序執行調度+內存分配回收+異常處理.net
程序計數器(Program Counter Register)線程
每一個線程有一個獨立的程序計數器
做用是用來存儲當前線程執行指令的鏈表,當有線程切換時,線程切換回來後恢復到正確的指令位置
這個程序計數器的功能主要有:下一條須要執行的字節碼指令,分支、循環、跳轉、異常處理、線程恢復
當執行java方法時,程序計數器指向JVM虛擬機中的虛擬機字節碼指令的地址,當執行的是native方法時,程序計數器值爲空「Undefined」
程序計數器內存是在線程開始時提早預留的,在JVM中沒有任何規定OutOfMemoryError 狀況的區域
Java 虛擬機棧(Java Virtual Machine Stacks)
棧與程序計數器是線程私有的,生命週期與線程一致
棧內主要存儲:局部變量表、操做棧、動態、連接、方法出口等
局部變量表存放的內容有:各類基本數據類型(boolean、byte、char、short、int、float、long、double)、對象引用(reference 類型,它不等同於對象自己,根據不一樣的虛擬機實現,它多是一個指向對象起始地址的引用指針,也可能指向一個表明對象的句柄或者其餘與此對象相關的位置)和returnAddress 類型(指向了一條字節碼指令的地址)
局部變量表所需的內存空間在編譯期間完成分配,當進入一個方法時,這個方法須要在幀中分配多大的局部變量空間是徹底肯定的,在方法運行期間不會改變局部變量表的大小。
StackOverflowError狀況:a. 線程請求的棧深度大於虛擬機所容許的深度, b. 超出固定長度棧的長度【若是虛擬機棧能夠動態擴展(當前大部分的Java 虛擬機均可動態擴展,只不過Java 虛擬機規範中也容許固定長度的虛擬機棧),當擴展時沒法申請到足夠的內存時會拋出OutOfMemoryError 異常】
如何寫一個棧異常:方法無線循環。超過棧深度就會出現棧異常,一直無限循環,一直存儲方法出口,會把棧內存耗光,也會報棧溢出的異常
棧的數據結構是後進先出,因此最新壓到棧底的應該是出口方法,等全部的局部變量和方法執行完後,調到出口方法
本地方法棧(Native Method Stacks)
本地方法棧(Native Method Stacks)與虛擬機棧所發揮的做用是很是類似的,其區別不過是虛擬機棧爲虛擬機執行Java 方法(也就是字節碼)服務,而本地方法棧則是爲虛擬機使用到的Native 方法服務。
Java 堆(JVM Heap)
Heap是JVM管理最大的一塊內容,Java是面嚮對象語言,主要的類型是引用類型,因此主要的存儲都是在堆裏存儲
Java 堆是被全部線程共享的一塊內存區域,在虛擬機啓動時建立
幾乎全部的對象實例都在Heap分配內存
Java 堆是垃圾回收器GC的工做場所
堆的存儲和磁盤同樣,是能夠不連續存儲的
堆通常都是動態擴展的,也有固定大小的堆
JVM的垃圾回收也是分代回收,分爲新生代和老年代,優勢是讓GC的過程快速高效,新生代頻繁(過時垃圾最多的地方),老年代不少都是全局的生命週期,回收也白費力氣
當有內存申請並沒有法分配內存空間時,就會報OutOfMemoryError
方法區(Method Area)
方法區(Method Area)與Java 堆同樣,是各個線程共享的內存區域,它用於存儲已被虛擬機加載的類信息、常量、靜態變量、即時編譯器編譯後的代碼等數據
不少人願意把方法區稱爲「永久代」(Permanent Generation),能夠選擇不實現垃圾收集
編譯後的代碼(.class)都是存放在方法區的,也是堆的存儲方式,這樣就好理解JVM的運行環了,找到根了
直接內存(Direct Memory)
數據庫鏈接,文件流,Socket鏈接,引用的Native資源等,都須要手動釋放,GC不會操做直接內存
在JDK 1.4 中新加入了NIO(New Input/Output)類,引入了一種基於通道(Channel)與緩衝區(Buffer)的I/O 方式,它可使用Native 函數庫直接分配堆外內存,而後經過一個存儲在Java 堆裏面的DirectByteBuffer 對象做爲這塊內存的引用進行操做。這樣能在一些場景中顯著提升性能,由於避免了在Java 堆和Native 堆中來回複製數據。
顯然,本機直接內存的分配不會受到Java 堆大小的限制,可是,既然是內存,則確定仍是會受到本機總內存(包括RAM 及SWAP 區或者分頁文件)的大小及處理器尋址空間的限制。
Java內存溢出調試
獲取Dump文件
根據Dump快照分析內存分配狀況
查看哪些是不改太大佔用的,進行分析
分時獲取兩個Dump,對比內存佔用狀況,分析趨勢
https://www.cnblogs.com/HDK2016/p/7226840.html?utm_source=itdadao&utm_medium=referral
想必讀者已經瞭解過native關鍵字了。這裏筆者就大體囊括一下,被native關鍵字修飾的方法叫作本地方法,本地方法和其它方法不同,本地方法意味着和平臺有關,所以使用了native的程序可移植性都不過高。另外native方法在JVM中運行時數據區也和其它方法不同,它有專門的本地方法棧。native方法主要用於加載文件和動態連接庫,因爲Java語言沒法訪問操做系統底層信息(好比:底層硬件設備等),這時候就須要藉助C語言來完成了。被native修飾的方法能夠被C語言重寫。
http://www.javashuo.com/article/p-zawkoqxn-md.html
https://baike.baidu.com/item/%E5%8F%A5%E6%9F%84/3527587
句柄是整個Windows編程的基礎。一個句柄是指使用的一個惟一的整數值,即一個4字節(64位程序中爲8字節)長的數值,來標識應用程序中的不一樣對象和同類中的不一樣的實例,諸如,一個窗口,按鈕,圖標,滾動條,輸出設備,控件或者文件等。
句柄和指針都是地址,不一樣之處在於:
(1)句柄所指的能夠是一個很複雜的結構,而且頗有多是與系統相關的,好比說線程的句柄,它指向的就是一個類或者結構,它和系統有很密切的關係。當一個線程因爲不可預料的緣由而終止時,系統就能夠返回它所佔用的的資料,如CPU ,內存等。反過來想能夠知道,這個句柄中的某一些項是與系統進行交互的。因爲Windows系統是一個多任務的系統,它隨時均可能要分配內存,回收內存,重組內存。
(2)指針也能夠指向一個複雜的結構,可是一般是用戶定義的,因此必須的工做都要用戶完成,特別是在刪除的時候。