微信網(wǎng)站是什么意思昆明網(wǎng)絡(luò)推廣公司排名
文章目錄
- 初識jvm
- 內(nèi)存結(jié)構(gòu)
- 程序計數(shù)器(寄存器)
- 棧
- 問題辨析
- 內(nèi)存溢出
- 線程診斷
- 本地方法棧
- Heap堆
- 內(nèi)存溢出
- 內(nèi)存診斷
- 方法區(qū)
- 內(nèi)存溢出
- 常量池
- stringTable
- 直接內(nèi)存
- 垃圾回收
初識jvm
JRE = JVM + 基礎(chǔ)類庫
JDK = JRE + 編譯工具
JavaSE = JDK + IDE工具
JavaEE = JDK + 應(yīng)用服務(wù)器 +IDE工具
jvm是java程序的運行環(huán)境
好處:
- 一次編寫,到處運行
- 自動內(nèi)存管理,垃圾回收功能
- 數(shù)組下標越界檢查
- 多態(tài)
學(xué)習(xí)路線:JVM內(nèi)存結(jié)構(gòu)–>垃圾回收GC–>Java Class–>ClassLoader–>JIT Compiler即時編譯器
內(nèi)存結(jié)構(gòu)
程序計數(shù)器(寄存器)
用來記住此線程下一條jvm指令的執(zhí)行地址
特點:
- 是線程私有的
- 不會存在內(nèi)存溢出(唯一不會內(nèi)存溢出的jvm內(nèi)存結(jié)構(gòu))
棧
每個棧都是一個線程運行需要的內(nèi)存空間
棧幀,每個方法運行時需要的內(nèi)存
每個線程只能有一個活動棧幀,對應(yīng)著當前正在執(zhí)行的那個方法
在調(diào)試里面可以看棧\棧幀\內(nèi)存\開銷等
問題辨析
垃圾回收是否涉及棧內(nèi)存?
不需要,棧幀運行完,自動回收
棧內(nèi)存定義分配越大越好嘛
不一定,棧內(nèi)存定義越大,同時運行的線程越少
方法內(nèi)的局部變量是否線程安全?
- 如果方法局部變量沒有逃離方法的作用訪問,它是線程安全的
- 如果是局部變量引用了對象,并逃離方法的作用方法(返回值),需要考慮線程安全
是不是線程安全的,主要看是不是有變量線程共享,有變量線程共享就可能引發(fā)安全問題,也要看后續(xù)采取的解決措施
內(nèi)存溢出
棧溢出異常:stackOverFlowError
一般一個棧為1024K大小
- 棧幀過多導(dǎo)致棧內(nèi)存溢出
- 棧幀過大導(dǎo)致棧內(nèi)存溢出
線程診斷
CPU占用過多
- 用
top
定位哪個進程對cpu的占用過高 ps H -eo pid,tid,%cpu | grep 進程id
(用ps命令進一步定位是哪個線程引起的cpu占用過高)jstack 進程id
,可以根據(jù)線程id找到有問題的線程,進一步定位到問題代碼的源碼行號
程序運行很長時間沒有結(jié)果
比如,死鎖- 還是用jstack 進程id排查
本地方法棧
存放一些不用java代碼實現(xiàn)的代碼,比如調(diào)用一些底層的C代碼(比如系統(tǒng)函數(shù),java實現(xiàn)不了的功能),提供內(nèi)存空間
Heap堆
通過new關(guān)鍵字,創(chuàng)建對象都會使用堆內(nèi)存
特點
- 線程共享,堆中對象都需要考慮線程安全的問題
- 有垃圾回收機制
內(nèi)存溢出
堆溢出異常:OutOfMemoryError
堆空間大小同樣可以設(shè)置
內(nèi)存診斷
jps
工具,查看當前系統(tǒng)中有哪些java進程jmap
工具,查看堆內(nèi)存占用情況,jmap -heap 進程id
jconsole
工具,圖形界面的,多功能的檢測工具,可以連續(xù)監(jiān)測jvisualvm
,可視化虛擬機jconsole的加強工具
方法區(qū)
方法區(qū)的存儲與堆的區(qū)別:
方法區(qū)內(nèi)容,類名\字段\方法的字節(jié)碼,靜態(tài)變量
堆內(nèi)容,new出來的對象
內(nèi)存溢出
- 1.8以前會導(dǎo)致永久代內(nèi)存溢出
- 1.8以后會導(dǎo)致元空間內(nèi)存溢出
從圖中可以看到,方法區(qū)一直是一個概念性的區(qū)域,1.6時,就是堆中的永久代,(其實圖中不應(yīng)該把堆和方法區(qū)分成兩塊)
1.8以后從堆中分離,放入本地內(nèi)存中
常量池
.class反編譯后可以顯示,類基本信息\常量池\類方法定義\包含了虛擬機指令
常量池會保存類的信息
常量池,就是一張表,虛擬機指令根據(jù)這張常量表找到要執(zhí)行的類名\方法名\參數(shù)類型\字面量等信息
運行時常量池,常量池是*.class文件中的,當該類被加載,它的常量池信息就會放入運行時常量池,并把里面的符號地址變?yōu)檎鎸嵉刂?/p>
stringTable
底層原理還是要看反編譯的class文件是怎么做的,因為java在語法上有語法糖等因素,不夠清晰