柚子快報(bào)邀請(qǐng)碼778899分享:初識(shí)JVM
柚子快報(bào)邀請(qǐng)碼778899分享:初識(shí)JVM
目錄
1.JVM(JAVA? Virtual Machine)
2.常見的JVM
3.jvm的組成部分
4.JVM內(nèi)存結(jié)構(gòu)
(1)Program Counter Register程序計(jì)數(shù)器(通過寄存器實(shí)現(xiàn)程序計(jì)數(shù)器)
(2)Java虛擬機(jī)棧(Java Virtual Machine Stacks)
(3)本地方法棧(Native Method Stacks)
(4)堆(Heap)
(5)方法區(qū)
1.JVM(JAVA? Virtual Machine)
(1)定義:Java程序的運(yùn)行環(huán)境(Java二進(jìn)制字節(jié)碼的運(yùn)行環(huán)境)
(2)好處
?一次編寫,到處運(yùn)行
?自動(dòng)內(nèi)存管理,垃圾回收功能
?數(shù)組下標(biāo)越界檢查
?實(shí)現(xiàn)多態(tài)(面向?qū)ο缶幊痰幕?,?shí)現(xiàn)了可擴(kuò)展性)
(3)比較
JAVAEE程序(JDK+IDE工具+應(yīng)用服務(wù)器)JAVASE程序(JDK+IDE工具)JDK(JVM+基礎(chǔ)類庫(kù)+編譯工具)JRE(JVM+基礎(chǔ)類庫(kù))JVM操作系統(tǒng)
2.常見的JVM
3.jvm的組成部分
4.JVM內(nèi)存結(jié)構(gòu)
(1)Program Counter Register程序計(jì)數(shù)器(通過寄存器實(shí)現(xiàn)程序計(jì)數(shù)器)
java源代碼->jvm指令(二進(jìn)制字節(jié)碼)->解釋器->機(jī)器碼->CPU
?程序計(jì)數(shù)器的作用:在上述流程中記住下一條jvm指令的執(zhí)行地址
?特點(diǎn)
1.線程私有的:每個(gè)線程都有自己的程序計(jì)數(shù)器。
2.不會(huì)存在內(nèi)存溢出。
(2)Java虛擬機(jī)棧(Java Virtual Machine Stacks)
·?線程運(yùn)行時(shí)需要的內(nèi)存空間。
· 一個(gè)棧由多個(gè)棧幀組成,棧幀(Frame)(每個(gè)方法運(yùn)行時(shí)需要的內(nèi)存空間):一個(gè)棧幀對(duì)應(yīng)著一次方法的調(diào)用。每個(gè)方法(參數(shù),局部變量,返回地址都需要內(nèi)存空間)需要的內(nèi)存稱為一個(gè)棧幀。
·?每一個(gè)方法被調(diào)用時(shí),對(duì)應(yīng)的棧幀被壓入棧中,調(diào)用結(jié)束后,釋放該棧幀所占用的內(nèi)存空間。
·?每個(gè)線程只能有一個(gè)活動(dòng)棧幀(當(dāng)前棧頂部的棧幀),對(duì)應(yīng)著當(dāng)前正在執(zhí)行的那個(gè)方法。
?問題辨析
1.垃圾回收是否涉及棧內(nèi)存?
不涉及
2.棧內(nèi)存分配越大越好?
NO,棧內(nèi)存越大,線程數(shù)越少。
·?"-Xss size" :指定棧內(nèi)存。
idea中在此設(shè)置棧內(nèi)存大?。?/p>
·?Linux,macOS,Oracle Solaris默認(rèn)棧內(nèi)存是1024K,Windows的棧內(nèi)存的默認(rèn)值依賴于虛擬內(nèi)存的值。
3.方法內(nèi)的局部變量是否線程安全?
· 是多個(gè)線程共享的:eg:當(dāng)局部變量為static的;局部變量作為返回值進(jìn)行返回時(shí);局部變量作為形參傳入時(shí),多個(gè)線程會(huì)訪問到這個(gè)局部變量,此時(shí)要考慮線程安全問題。
· 是每個(gè)線程私有的:eg:當(dāng)局部變量沒有static修飾,且局部變量不是作為返回值進(jìn)行返回,局部變量不是作為形參傳入時(shí),此時(shí)是線程安全的,因?yàn)槊看握{(diào)用方法都會(huì)有自己的一個(gè)棧幀,不會(huì)影響到其他線程的運(yùn)行結(jié)果。
總結(jié):如果方法內(nèi)局部變量沒有逃離方法的作用范圍,則是線程安全的;如果是局部變量引用了對(duì)象,并逃離了方法的作用范圍,則需要考慮線程安全問題。
?棧內(nèi)存溢出
1.棧幀過多導(dǎo)致棧內(nèi)存溢出(遞歸調(diào)用)
2.棧幀過大導(dǎo)致棧內(nèi)存溢出(這種情況出現(xiàn)的不多)
?線程運(yùn)行診斷
1.CPU占用過多如何定位是哪個(gè)線程的影響(Linux中)?
· 用top命令定位哪個(gè)進(jìn)程對(duì)CPU占用率過高。
· ”ps H -eo pid,tid,%cpu | grep 進(jìn)程id“ :進(jìn)一步定位是哪個(gè)線程引起的CPU占用率過高。
· "jstack 進(jìn)程id":根據(jù)線程id定位到有問題的線程,進(jìn)一步定位到有問題的源碼的源碼行號(hào)。(將第二步中十進(jìn)制的線程id轉(zhuǎn)換為十六進(jìn)制的數(shù),再在查到的線程以及源碼中找到對(duì)應(yīng)地址的源碼)
十進(jìn)制:32665->十六進(jìn)制:7f99
2.程序運(yùn)行很長(zhǎng)時(shí)間沒有得到結(jié)果
"jstack 進(jìn)程id":查找源碼中有問題的行號(hào)。
原因:線程A中想要獲取的資源被其他線程所占用了。
(3)本地方法棧(Native Method Stacks)
·?不是由Java代碼編寫的方法。由c/c++編寫的方法,Java通過本地方法接口調(diào)用進(jìn)行使用。
· 是線程私有的。
eg:clone(),hashcode(),notify(),notifyAll(),wait()......
(4)堆(Heap)
堆空間大小的設(shè)置:”-Xmx size"
?定義:通過new關(guān)鍵字,創(chuàng)建對(duì)象都會(huì)使用堆內(nèi)存。
?特點(diǎn):是線程共享的,堆中對(duì)象都要考慮線程安全問題;堆有垃圾回收機(jī)制。
?堆內(nèi)存溢出
多個(gè)對(duì)象都在被使用,不能被回收,且被使用的對(duì)象數(shù)量在增加,會(huì)導(dǎo)致堆內(nèi)存溢出。
?堆內(nèi)存診斷
1.jps工具:查看當(dāng)前系統(tǒng)中有哪些Java進(jìn)程。
2.jmap工具:查看堆內(nèi)存占用情況。
"jmp -heap 進(jìn)程id":查看該進(jìn)程的堆內(nèi)存占用情況。
3.jconsole工具:圖形界面的,多功能的檢測(cè)工具,可以連續(xù)檢測(cè)。
命令行執(zhí)行jconsole命令,會(huì)出現(xiàn)一個(gè)圖形化界面,顯示詳細(xì)信息:?
?案例
垃圾回收后,內(nèi)存占用仍然很高。
jVisvalVM工具:可視化工具。
抓取當(dāng)前堆的快照,進(jìn)一步對(duì)里面的詳細(xì)內(nèi)容進(jìn)行分析。
根據(jù)具體查找,對(duì)代碼進(jìn)行定位和分析。
(5)方法區(qū)
?JVM規(guī)范-方法區(qū)的定義
1.方法區(qū)是所有JVMJava虛擬機(jī)線程共享的區(qū),存儲(chǔ)了和類的結(jié)構(gòu)相關(guān)的信息(運(yùn)行時(shí)常量池,類的成員變量,方法數(shù)據(jù),成員方法和構(gòu)造器的代碼部分,包括一些特殊方法:主要指類的構(gòu)造器)
2.方法區(qū)是在虛擬機(jī)啟動(dòng)的時(shí)候被創(chuàng)建。邏輯上是堆的組成部分(這個(gè)規(guī)范并不強(qiáng)制方法區(qū)的位置)
組成(HotSpot,Oracle):
?方法區(qū)內(nèi)存溢出
· 1.8以前會(huì)導(dǎo)致永久代內(nèi)存溢出
永久代大小設(shè)置:"-XX MaxPermSize=大小"
· 1.8之后會(huì)導(dǎo)致元空間內(nèi)存溢出
元空間大小設(shè)置:"-XX MaxMetaspaceSize=大小"
· 出現(xiàn)方法區(qū)內(nèi)存溢出的場(chǎng)景(加載類時(shí),使用不當(dāng)):Spring,Mybatis中用到的CGLib
?常量池:給指令提供常量符號(hào),根據(jù)這些常量符號(hào)進(jìn)行在常量池表中進(jìn)行查找。
定義:就是一張表,虛擬機(jī)指令根據(jù)這張常量表找到要執(zhí)行的類名,方法名,參數(shù)類型等信息。
二進(jìn)制字節(jié)碼(類基本信息,常量池,類方法定義,包含了虛擬機(jī)指令)
"javap -v *.class文件":顯示反編譯后的詳細(xì)信息。
根據(jù)虛擬機(jī)指令,查常量池的表:
確定這些指令是要執(zhí)行的具體信息。
?運(yùn)行時(shí)常量池
常量池是*.class文件中的,當(dāng)該類被加載,它的常量池信息就會(huì)被放入運(yùn)行時(shí)常量池,并把里面的符號(hào)地址變?yōu)檎鎸?shí)地址。
柚子快報(bào)邀請(qǐng)碼778899分享:初識(shí)JVM
推薦文章
本文內(nèi)容根據(jù)網(wǎng)絡(luò)資料整理,出于傳遞更多信息之目的,不代表金鑰匙跨境贊同其觀點(diǎn)和立場(chǎng)。
轉(zhuǎn)載請(qǐng)注明,如有侵權(quán),聯(lián)系刪除。