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