Author: Lijbjava
Email:lijb1121@163.com算法
1、JVM介紹數組
JVM是Java Virtual Machine(Java虛擬機)的縮寫,JVM是一種用於計算設備的規範,它是一個虛構出來的計算機,是經過在實際的計算機上仿真模擬各類計算機功能來實現的。 Java語言的一個很是重要的特色就是與平臺的無關性。而使用Java虛擬機是實現這一特色的關鍵。通常的高級語言若是要在不一樣的平臺上運行,至少須要編譯成不一樣的目標代碼。而引入Java語言虛擬機後,Java語言在不一樣平臺上運行時不須要從新編譯。Java語言使用Java虛擬機屏蔽了與具體平臺相關的信息,使得Java語言編譯程序只需生成在Java虛擬機上運行的目標代碼(字節碼),就能夠在多種平臺上不加修改地運行。Java虛擬機在執行字節碼時,把字節碼解釋成具體平臺上的機器指令執行。這就是Java的可以「一次編譯,處處運行」的緣由。
2、JAVA代碼編譯和執行過程緩存
Java代碼編譯和執行的整個過程包含了如下三個重要的機制:tomcat
Java源碼編譯機制安全
Java 源碼編譯由如下三個過程組成:多線程
流程圖以下所示:併發
最後生成的class文件由如下部分組成:ide
· 結構信息。包括class文件格式版本號及各部分的數量與大小的信息函數
· 元數據。對應於Java源碼中聲明與常量的信息。包含類/繼承的超類/實現的接口的聲明信息、域與方法聲明信息和常量池
· 方法信息。對應Java源碼中語句和表達式對應的信息。包含字節碼、異常處理器表、求值棧與局部變量區大小、求值棧的類型記錄、調試符號信息
類加載機制
JVM的類加載是經過ClassLoader及其子類來完成的,類的層次關係和加載順序能夠由下圖來描述:
1)Bootstrap ClassLoader
負責加載$JAVA_HOME中jre/lib/rt.jar裏全部的class,由C++實現,不是ClassLoader子類
2)Extension ClassLoader
負責加載java平臺中擴展功能的一些jar包,包括$JAVA_HOME中jre/lib/*.jar或-Djava.ext.dirs指定目錄下的jar包
3)App ClassLoader
負責記載classpath中指定的jar包及目錄中class
4)Custom ClassLoader
屬於應用程序根據自身須要自定義的ClassLoader,如tomcat、jboss都會根據j2ee規範自行實現ClassLoader加載過程當中會先檢查類是否被已加載,檢查順序是自底向上,從Custom ClassLoader到BootStrap ClassLoader逐層檢查,只要某個classloader已加載就視爲已加載此類,保證此類只全部ClassLoader加載一次。而加載的順序是自頂向下,也就是由上層來逐層嘗試加載此類。
類執行機制
JVM是基於棧的體系結構來執行class字節碼的。線程建立後,都會產生程序計數器(PC)和棧(Stack),程序計數器存放下一條要執行的指令在方法內的偏移量,棧中存放一個個棧幀,每一個棧幀對應着每一個方法的每次調用,而棧幀又是由局部變量表、操做數棧、動態連接、方法返回地址等組成,局部變量區用於存放方法中的局部變量和參數,操做數棧中用於存放方法執行過程當中產生的中間結果。棧的結構在下文會展開詳解:
3、JVM內存結構詳解
虛擬機棧
每一個線程執行每一個方法的時候都會在棧中申請一個棧幀,每一個棧幀包括局部變量區、操做數棧、動態連接、方法返回地址【附加信息】,用於存放這次方法調用過程當中的臨時變量、參數和中間結果。
-Xss**:**設置每一個線程的堆棧大小. JDK1.5+ 每一個線程堆棧大小爲 1M,通常來講若是棧不是很深的話, 1M 是絕對夠用了的。
A**、JVM棧**:伴隨每個線程的啓動,在內存中建立一個對應的JVM棧,用於存儲「棧幀。
棧幀結構:棧幀是JVM棧描述方法執行的內存模型。包含了局部變量表、操做數棧、動態連接、方法返回地址等。
異常:StackOverflowError、OutOfMemoryError.
B**、棧幀結構(Stack Frame)**:棧幀是JVM棧描述方法執行的內存模型,每個方法在執行的同時都會建立一個棧幀,其中包含了局部變量表、操做數棧、動態連接、方法返回地址等。
局部變量表(Local Variable Table)
一組變量值的存儲空間,用於存放方法在執行過程當中所須要的參數和局部變量,局部變量表中的每個存儲空間稱爲「變量槽」(Variable Slot),可存儲的數據類型:byte、boolean、short、char、int、float、reference、returnAddress**(已過期)**。對於double、long類型須要2個連續的Slot進行存儲,局部變量表的容量由Code屬性的max_locals在編譯期肯定。
操做數棧(Operand Stack)
操做數棧又稱爲操做棧、表達式棧、是虛擬機的工做區。經過JVM字節碼指令對「局部變量表」中的數據進行提取、調用、計算、存儲等操做。操做數棧的深度由Code屬性的max_stacks在編譯期肯定。
動態連接
每個棧幀內部都包含一個指向運行時常量池中該棧幀所屬方法的引用。在每一次方法運行期間,動態的將符號引用轉換成直接引用(入口地址)。 靜態解析是指,類加載或首次調用期間將 #1 methodref xxx.xxx.xxx.fn()V 轉換成該方法的如接口地址。 動態解析是指,每次調用期間將 #2 methodref xxx.xxx.xxx.fn1()V轉換成該方法的入口地址。
以下代碼:
public class TestStack { public static void main(String[] args) { int x=10; int y=20; int z=x+y; } }
反編譯以後在棧空間運行狀況以下圖:
方法返回地址(Method Renturn Address)
方法的結束分爲正常結束和異常結束。
正常結束:當前棧幀承擔着恢復調用者狀態的責任,其中包括恢復調用者的局部變量表、操做數棧、正確遞增程序計數器、將返回值壓入調用者的操做數棧。
異常結束:若是當前方法中沒有處理此種異常,當前棧幀恢復調用者狀態的同時,不會返回任何返回值,而是經過athrow指令將當前異常拋給調用者。
除了要給予調用者操做結果之外,還要調整爲PC計數器的值,以指向方法調用指令的後一行指令。
C、棧空間的異常:
StackOverflowError:
無窮遞歸 可用內存下自動擴充棧深度,若是空間不足、沒法擴充時,則拋出StackOverflowErro。
OutOfMemoryError:
無限建立線程對象。 全部可用內存空間所有分配給JVM去建立線程,會致使OutOfMemoryError,因虛擬機線程會調用操做系統線程,可能致使計算機假死。
本地方法棧
本地方法棧內存結構和運行原理與虛擬機棧同樣,不一樣之處在於本地方法棧用於支持Native方法的執行,存儲了每一個Native方法調用的狀態
堆
Java堆(Java Heap)
由JVM自動管理的線程區域,在JVM啓動時建立,用於存儲對象。堆能夠處於邏輯上連續、物理上不連續的空間當中,既能夠實現爲固定大小,也能夠實現爲可擴展的,當前主流虛擬機實現都是可擴展的,可經過相關的虛擬機參數進行配置。
全部經過new關鍵字建立的對象都在堆中分配,堆的大小能夠經過-Xmx和-Xms來控制。堆被劃分爲新生代和老年代,新生代又被進一步劃分爲Eden和Survivor區, Survivor又由From Space和To Space組成。(注:有些資料裏也會把兩個同樣的survivor區稱爲s1和s2區,本質都是同樣的)
新生代。新建的對象都是用新生代分配內存,Eden空間不足的時候,會把存活的對象轉移到Survivor中,新生代大小能夠由-Xmn來控制,也能夠用-XX:SurvivorRatio來控制Eden和Survivor的比例
老年代。用於存放新生代中通過屢次垃圾回收仍然存活的對象
持久帶(Permanent Space)實現方法區,主要存放全部已加載的類信息,方法信息,常量池等等。可經過-XX:PermSize和-XX:MaxPermSize來指定持久帶初始化值和最大值。Permanent Space並不等同於方法區,只不過是Hotspot JVM用Permanent Space來實現方法區而已,有些虛擬機沒有Permanent Space而用其餘機制來實現方法區。
-Xmx:最大堆內存,如:-Xmx512m -Xms:初始時堆內存,如:-Xms256m -Xmn:新生代大小 -XX:MaxNewSize:最大年輕區內存 -XX:NewSize:初始時年輕區內存.一般爲 Xmx 的 1/3 或 1/4。新生代 = Eden + 2 個 Survivor 空間。實際可用空間爲 = Eden + 1 個 Survivor,即 90%。 -XX:MaxPermSize:最大持久帶內存 -XX:PermSize:初始時持久帶內存 -XX:+PrintGCDetails:打印 GC 信息 -XX:NewRatio 新生代與老年代的比例,如 –XX:NewRatio=2,則新生代佔整個堆空間的1/3,老年代佔2/3 -XX:SurvivorRatio 新生代中 Eden 與 Survivor 的比值。默認值爲 8。即 Eden 佔新生代空間的 8/10,另外兩個 Survivor 各佔 1/10,在jdk7 update23版本之前,默認Eden:surivor1=8:1的比例,以後版本默認爲6:1,該比例都是能夠經過參數改變的。  -XX:PretenureSizeThreshold:設置對象的最大閾值(在Parallel收集器下無效)配上-XX:+UseSerialGC,使用Serial收集器便可。
堆空間的異常:OutOfMemoryError
新生代+老年代超過-Xmx上限。則會拋出OutOfMemoryError
非堆
線程共享區域,主要存儲Class文件被加載後的運行時相關信息。其中包含:代碼緩存、方法區、類指針壓縮空間(jdk8)。
方法區(Method Area)
JVM自動管理的線程共享區域,在JVM啓動時建立,用於存儲全部Class文件相關的「元數據」或者叫類信息、靜態變量、字符串、常量、常量池(字面值、符號引用)、字段描述、方法描述。
類型描述信息:
類的全限定名、父類的全限定名、類或接口的標記、類的修飾符、已排序的接口列表。
類型主體信息:
實例變量信息、靜態變量信息、方法信息、指向該類的引用、指向該類的類加載器引用。
運行時常量池
常量值、字段引用、方法引用、接口方法引用。
方法代碼:
方法字節碼操做數棧大小局部變量表大小、局部變量表、異常表、每一個異常處理器、開始點、結束點、異常處理代碼的程序計數器、被捕獲的異常對應的常量池下標。
方法區相關的參數:
·-XX:MetaspaceSize=?元空間初始大小(jdk1.7以前-XX:PermSize) ·-XX:MaxMetaspaceSize=?元空間最大上限(jdk1.7以前-XX:MaxPermSize) 對於方法區若是不給上限,那最大上限就是整個操做系統的內存最大容量。 ·-XX:+TraceClassLoading:跟蹤類的加載信息 ·-XX:+TraceClassLoadingPreorder:跟蹤被引用到的全部類的加載信息 ·-XX:+TraceClassResolution:跟蹤常量池 ·-XX:+TraceClassUnloading:跟蹤類的卸載信息 ·-XX:TraceLoaderConstraints:跟蹤類加載器約束的相關信息
類指針壓縮空間(Compressed Class Space)
每一個對象的對象頭中除了有MarkWord(mark)之外,還有一個指向它自身類的指針(klass),在32bit和64bit虛擬機中,klass指針大小分別是32bit和64bit。64bit平臺上默認開啓類指針壓縮後可將klass壓縮爲32bit.
類指針壓縮空間相關的參數:
·-XX:+UseCompressedClassPointers 開啓類指針壓縮空間 ·-XX:+ CompressedClassSpaceSize=?設置類指針壓縮空間的大小 ·-XX:+UseCompressedOops開啓對象的類指針壓縮功能
代碼緩存區(Code Cache)
HotSpot具備即時編譯,能夠基於計數器的熱點探測功能發現「熱點代碼」(頻繁調用的方法或方法中的循環體)。
緩存區包含Client Compiler和Server Compiler,簡稱C一、C2.
經過參數-XX:CompileThreshold=?可進行觸發條件的控制。
Code Cache主要用於存儲被「JIT Compiler」編譯生成的本地平臺相關的機器碼。
非堆區的異常:OutOfMemoryError
Metaspace超過-XX:MaxMetaspaceSize的上限,則拋出OutOfMemoryError,默認無上限。
Compressed Class Spac超過-XX:CompressedClassSpaceSize的上限,則拋出OutOfMemoryError,默認1G.
對整個運行時數據區的總結:
4、JVM垃圾回收
垃圾的斷定:
1)引用計數算法(Reference Counting):
比較古老的回收算法。原理是此對象有一個引用,即增長一個計數,刪除一個引用則減小一個計數。垃圾回收時,只用收集計數爲0的對象。此算法的缺點是沒法處理循環引用或者相互引用的問題。目前虛擬機不會採用該算法!!!
2)可達性分析算法(Reachability Analysis):
也稱爲「根搜索算法」,使用「常量引用的對象」、「靜態屬性引用的對象」、「局部變量引用的對象」做爲「GC Root」對象。以「GC Root」做爲起始節點,依次向下查找對象間的引用關係(引用鏈),若是引用關係可達,則表示該對象爲存活對象;若是引用關係不可達,則表示爲垃圾對象。對於相互引用,但「GC Root」不可達的對象,也視爲垃圾對象。 枚舉根節點(Enumeration GC Root): JVM維護了一組GC Root的集合,稱爲「GC Roo Set」(根集合),以每一個GC Root 爲地點,展開「可達性分析」進而標記垃圾對象。此操做必須在確保一致性的快照中進行,保證全部引用在此期間不存在變化的狀況,會觸發全部用戶線程暫停(掛起),官方稱爲「Stop The Word」(STW)。
垃圾回收算法:
一、標記-清除(Mark-Sweep):
此算法執行分兩階段。第一階段從引用根節點開始標記全部被引用的對象,第二階段遍歷整個堆,把未標記的對象清除。此算法須要暫停整個應用,缺點:會產生內存碎片。形成內存不連續,若是之後出現大對象可能會致使對象無法直接存放,須要壓縮整理內存,從而致使效率很慢。
二、複製算法(Copying):
此算法把內存空間劃爲兩個相等的區域,每次只使用其中一個區域。垃圾回收時,遍歷當前使用區域,把正在使用中的對象複製到另一個區域中。算法每次只處理正在使用中的對象,所以複製成本比較小,同時複製過去之後還能進行相應的內存整理(至關於的複製過程當中直接進行了壓縮整理),不會出現「碎片」問題。固然,此算法的缺點也是很明顯的,就是須要兩倍內存空間。若是有4G的內存時每次只能使用2G.浪費內存。
三、標記-整理(Mark-Compact)
也稱爲標記-壓縮算法,此算法結合了「標記-清除」和「複製」兩個算法的優勢。也是分兩階段,第一階段從根節點開始標記全部被引用對象,第二階段遍歷整個堆,把清除未標記對象而且把存活對象「壓縮」到堆的其中一塊,按順序排放。此算法避免了「標記-清除」的碎片問題,同時也避免了「複製」算法的空間問題。
四、分代收集算法(Generational Collection)
新生代:採用複製算法,Eden+From存儲保留To;Eden+To存儲保留From.
老年代:採用標記-清楚算法或者標記-壓縮算法。
一、新生代的GC: 新生代一般存活時間較短,所以基於Copying算法來進行回收,所謂Copying算法就是掃描出存活的對象,並複製到一塊新的徹底未使用的空間中(在新生代的兩個survivor區域之間複製來複制去。),對應於新生代,就是在Eden和From Space或To Space之間copy。新生代採用空閒指針的方式來控制GC觸發,指針保持最後一個分配的對象在新生代區間的位置,當有新的對象要分配內存時,用於檢查空間是否足夠,不夠就觸發GC。當連續分配對象時,對象會逐漸從eden到survivor,最後到老年代。
在執行機制上JVM提供了串行GC(Serial GC)、並行回收GC(Parallel Scavenge)和並行GC(ParNew)
1)串行GC
在整個掃描和複製過程採用單線程的方式來進行,適用於單CPU、新生代空間較小及對暫停時間要求不是很是高的應用上,是client級別默認的GC方式,能夠經過-XX:+UseSerialGC來強制指定
2)並行回收GC
在整個掃描和複製過程採用多線程的方式來進行,適用於多CPU、對暫停時間要求較短的應用上,是server級別默認採用的GC方式,可用-XX:+UseParallelGC來強制指定,用-XX:ParallelGCThreads=4來指定線程數
3)並行GC
與老年代的併發GC配合使用
二、老年代的GC:
老年代與新生代不一樣,對象存活的時間比較長,比較穩定,所以採用標記壓縮(Mark)算法來進行回收,所謂標記就是掃描出存活的對象,而後再進行回收未被標記的對象,把內存壓縮出來。回收後對用空出的空間要麼進行合併,要麼標記出來便於下次進行分配,總之就是要減小內存碎片帶來的效率損耗。在執行機制上JVM提供了串行GC(Serial MSC)、並行GC(parallel MSC)和併發GC(CMS),具體算法細節還有待進一步深刻研究。
以上各類GC機制是須要組合使用的,指定方式由下表所示:
指定方式 新生代GC方式 老年代GC方式 -XX:+UseSerialGC 串行GC 串行GC
-XX:+UseParallelGC 並行回收GC 並行GC
-XX:+UseConeMarkSweepGC 並行GC 併發GC
-XX:+UseParNewGC 並行GC 串行GC
-XX:+UseParallelOldGC 並行回收GC 並行GC
-XX:+ UseConeMarkSweepGC -XX:+UseParNewGC 串行GC 併發GC
不支持的組合 一、-XX:+UseParNewGC -XX:+UseParallelOldGC 二、-XX:+UseParNewGC -XX:+UseSerialGC
5、JVM優化原則
JVM型號:
首先須要注意的是在對JVM內存調優的時候不能只看操做系統級別Java進程所佔用的內存,這個數值不能準確的反應堆內存的真實佔用狀況,由於GC事後這個值是不會變化的,所以內存調優的時候要更多地使用JDK提供的內存查看工具,好比JConsole和Java VisualVM。 對JVM內存的系統級的調優主要的目的是減小GC的頻率和Full GC的次數,過多的GC和Full GC是會佔用不少的系統資源(主要是CPU),影響系統的吞吐量(吞吐量:就是這個時刻這個CPU可以同時處理的線程或者進程)。特別要關注Full GC,由於它會對整個堆進行整理,致使Full GC通常因爲如下幾種狀況:
老年代空間不足 調優時儘可能讓對象在新生代GC時被回收、讓對象在新生代多存活一段時間和不要建立過大的對象及數組避免直接在老年代建立對象
Pemanet Generation空間不足 增大Perm Gen空間,避免太多靜態對象
統計獲得的GC後晉升到老年代的平均大小大於老年代剩餘空間
控制好新生代和老年代的比例
System.gc()被顯示調用 垃圾回收不要手動觸發,儘可能依靠JVM自身的機制
調優手段主要是經過控制堆內存的各個部分的比例和GC策略來實現,下面來看看各部分比例不良設置會致使什麼後果
1)新生代設置太小 一是新生代GC次數很是頻繁,增大系統消耗;二是致使大對象直接進入老年代,佔據了老年代剩餘空間,誘發Full GC
2)新生代設置過大 一是新生代設置過大會致使老年代太小(堆總量必定),從而誘發Full GC;二是新生代GC耗時大幅度增長, 通常說來新生代佔整個堆1/3比較合適;新生代分配太大或者過小都會誘發Full GC的觸發。
3)Survivor設置太小 致使對象從eden直接到達老年代,下降了在新生代的存活時間
4)Survivor設置過大 致使eden太小,增長了GC頻率。另外,經過-XX:MaxTenuringThreshold=n來控制新生代存活時間,儘可能讓對象在新生代被回收
由內存管理和垃圾回收可知新生代和老年代都有多種GC策略和組合搭配,選擇這些策略對於咱們這些開發人員是個難題,JVM提供兩種較爲簡單的GC策略的設置方式
1)吞吐量優先 JVM以吞吐量爲指標,自行選擇相應的GC策略及控制新生代與老年代的大小比例,來達到吞吐量指標。這個值可由-XX:GCTimeRatio=n來設置
2)暫停時間優先 JVM以暫停時間爲指標,自行選擇相應的GC策略及控制新生代與老年代的大小比例,儘可能保證每次GC形成的應用中止時間都在指定的數值範圍內完成。這個值可由-XX:MaxGCPauseRatio=n來設置
6、JVM參數配置
一)、堆設置
-Xms:初始堆大小 -Xmx:最大堆大小 -XX:NewSize=n:設置年輕代大小 -XX:NewRatio=n:設置年輕代和年老代的比值。如:爲3,表示年輕代與年老代比值爲1:3,年輕代佔整個年輕代年老代和的1/4 -XX:SurvivorRatio=n:年輕代中Eden區與兩個Survivor區的比值。注意Survivor區有兩個。如:3,表示Eden:Survivor=3:2,一個Survivor區佔整個年輕代的1/5 -XX:MaxPermSize=n:設置持久代大小 概括: -verbose:class:後面沒有X的都是相對比較持久的參數 -X:一個X爲可變或可動態的參數,相對來來講可能在後續的版本會有一些改變。 -XX:兩個X這樣的參數就是頻繁變化的,頻繁增刪的,好比可能在jdk6有而在jdk7就沒有了,或者jdk8又有了。。。
基礎分配分配策略
優化分配策略
A.快速分配:
使用bump-the-pointer(指針碰撞)進行快速的連續空間分配,多線程下必須線程安全。 Thread-Local Allocation Buffer(線程局部分配緩存): 在Eden區默認劃分低於1%de線程私有空間,可在不加鎖狀況下使用「指針碰撞」,單個對象過大沒法存入TLAB時,再存人Eden區-XX:+UseTLAB -XX:+UseTLAB:jdk7以後默認是開啓的。
B.棧上分配:
逃逸分析:分析對象的動態做用域。-XX:+DoEscapeAnalysis.在jdk7也默認開啓。如下兩種狀況下對象在棧上分配比在堆上分配效率高10倍之多。 線程逃逸:該對象沒法在線程之外的位置訪問,則伴隨JVM棧銷燬而消失。 方法逃逸:該對象沒法在方法之外的位置訪問,則伴隨棧幀出棧而消失。
標量替換:-XX:+EliminateAllocations.-若是不存在逃逸,直接存儲對象的各個成員變量。標量替換和逃逸分析相輔相成,兩者缺一不可,只有這樣才能在棧上分配,才能把一個對象拆解成基本類型進而存儲到咱們的棧幀結構當中。 同步消除:若是不存在逃逸同步措施便可直接清除。-XX:+EliminateLocks.
二)、收集器設置
-XX:+UseSerialGC:設置串行收集器 -XX:+UseParallelGC:設置並行收集器 -XX:+UseParalledlOldGC:設置並行年老代收集器 -XX:+UseConcMarkSweepGC:設置併發收集器
三)、垃圾回收統計信息
-XX:+PrintGC -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -Xloggc:filename
四)、並行收集器設置
-XX:+CMSIncrementalMode:設置爲增量模式。適用於單CPU狀況。 -XX:ParallelGCThreads=n:設置並行收集器收集時使用的CPU數。並行收集線程數。 -XX:MaxGCPauseMillis=n:設置並行收集最大暫停時間 -XX:GCTimeRatio=n:設置垃圾回收時間佔程序運行時間的百分比。公式爲1/(1+n)
7、JVM字節碼指令
常量入棧指令
指令碼 操做碼(助記符) 操做數 描述(棧指操做數棧)
0x01 aconst_null null值入棧。
0x02 iconst_m1 -1(int)值入棧。
0x03 iconst_0 0(int)值入棧。
0x04 iconst_1 1(int)值入棧。
0x05 iconst_2 2(int)值入棧。
0x06 iconst_3 3(int)值入棧。
0x07 iconst_4 4(int)值入棧。
0x08 iconst_5 5(int)值入棧。
0x09 lconst_0 0(long)值入棧。
0x0a lconst_1 1(long)值入棧。
0x0b fconst_0 0(float)值入棧。
0x0c fconst_1 1(float)值入棧。
0x0d fconst_2 2(float)值入棧。
0x0e dconst_0 0(double)值入棧。
0x0f dconst_1 1(double)值入棧。
0x10 bipush valuebyte valuebyte值帶符號擴展成int值入棧。
0x11 sipush valuebyte1 valuebyte2 (valuebyte1 << 8) | valuebyte2 值帶符號擴展成int值入棧。 0x12 ldc indexbyte1 常量池中的常量值(int, float, string reference, object reference)入棧。 0x13 ldc_w indexbyte1 indexbyte2 常量池中常量(int, float, string reference, object reference)入棧。 0x14 ldc2_w indexbyte1 indexbyte2 常量池中常量(long, double)入棧。
局部變量值轉載到棧中指令
指令碼 操做碼(助記符) 操做數 描述(棧指操做數棧)
0x19 (wide)aload indexbyte 從局部變量indexbyte中裝載引用類型值入棧。
0x2a aload_0 從局部變量0中裝載引用類型值入棧。
0x2b aload_1 從局部變量1中裝載引用類型值入棧。
0x2c aload_2 從局部變量2中裝載引用類型值入棧。
0x2d aload_3 從局部變量3中裝載引用類型值入棧。
0x15 (wide)iload indexbyte 從局部變量indexbyte中裝載int類型值入棧。
0x1a iload_0 從局部變量0中裝載int類型值入棧。
0x1b iload_1 從局部變量1中裝載int類型值入棧。
0x1c iload_2 從局部變量2中裝載int類型值入棧。
0x1d iload_3 從局部變量3中裝載int類型值入棧。
0x16 (wide)lload indexbyte 從局部變量indexbyte中裝載long類型值入棧。
0x1e lload_0 從局部變量0中裝載int類型值入棧。
0x1f lload_1 從局部變量1中裝載int類型值入棧。
0x20 lload_2 從局部變量2中裝載int類型值入棧。
0x21 lload_3 從局部變量3中裝載int類型值入棧。
0x17 (wide)fload indexbyte 從局部變量indexbyte中裝載float類型值入棧。
0x22 fload_0 從局部變量0中裝載float類型值入棧。
0x23 fload_1 從局部變量1中裝載float類型值入棧。
0x24 fload_2 從局部變量2中裝載float類型值入棧。
0x25 fload_3 從局部變量3中裝載float類型值入棧。
0x18 (wide)dload indexbyte 從局部變量indexbyte中裝載double類型值入棧。
0x26 dload_0 從局部變量0中裝載double類型值入棧。
0x27 dload_1 從局部變量1中裝載double類型值入棧。
0x28 dload_2 從局部變量2中裝載double類型值入棧。
0x29 dload_3 從局部變量3中裝載double類型值入棧。
0x32 aaload 從引用類型數組中裝載指定項的值。
0x2e iaload 從int類型數組中裝載指定項的值。
0x2f laload 從long類型數組中裝載指定項的值。
0x30 faload 從float類型數組中裝載指定項的值。
0x31 daload 從double類型數組中裝載指定項的值。
0x33 baload 從boolean類型數組或byte類型數組中裝載指定項的值(先轉換爲int類型值,後壓棧)。 0x34 caload 從char類型數組中裝載指定項的值(先轉換爲int類型值,後壓棧)。
0x35 saload 從short類型數組中裝載指定項的值(先轉換爲int類型值,後壓棧)。
將棧頂值保存到局部變量中指令
指令碼 操做碼(助記符) 操做數 描述(棧指操做數棧)
0x3a (wide)astore indexbyte 將棧頂引用類型值保存到局部變量indexbyte中。
0x4b astroe_0 將棧頂引用類型值保存到局部變量0中。
0x4c astore_1 將棧頂引用類型值保存到局部變量1中。
0x4d astore_2 將棧頂引用類型值保存到局部變量2中。
0x4e astore_3 將棧頂引用類型值保存到局部變量3中。
0x36 (wide)istore indexbyte 將棧頂int類型值保存到局部變量indexbyte中。
0x3b istore_0 將棧頂int類型值保存到局部變量0中。
0x3c istore_1 將棧頂int類型值保存到局部變量1中。
0x3d istore_2 將棧頂int類型值保存到局部變量2中。
0x3e istore_3 將棧頂int類型值保存到局部變量3中。
0x37 (wide)lstore indexbyte 將棧頂long類型值保存到局部變量indexbyte中。
0x3f lstore_0 將棧頂long類型值保存到局部變量0中。
0x40 lstore_1 將棧頂long類型值保存到局部變量1中。
0x41 lstore_2 將棧頂long類型值保存到局部變量2中。
0x42 lstroe_3 將棧頂long類型值保存到局部變量3中。
0x38 (wide)fstore indexbyte 將棧頂float類型值保存到局部變量indexbyte中。
0x43 fstore_0 將棧頂float類型值保存到局部變量0中。
0x44 fstore_1 將棧頂float類型值保存到局部變量1中。
0x45 fstore_2 將棧頂float類型值保存到局部變量2中。
0x46 fstore_3 將棧頂float類型值保存到局部變量3中。
0x39 (wide)dstore indexbyte 將棧頂double類型值保存到局部變量indexbyte中。
0x47 dstore_0 將棧頂double類型值保存到局部變量0中。
0x48 dstore_1 將棧頂double類型值保存到局部變量1中。
0x49 dstore_2 將棧頂double類型值保存到局部變量2中。
0x4a dstore_3 將棧頂double類型值保存到局部變量3中。
0x53 aastore 將棧頂引用類型值保存到指定引用類型數組的指定項。
0x4f iastore 將棧頂int類型值保存到指定int類型數組的指定項。
0x50 lastore 將棧頂long類型值保存到指定long類型數組的指定項。
0x51 fastore 將棧頂float類型值保存到指定float類型數組的指定項。
0x52 dastore 將棧頂double類型值保存到指定double類型數組的指定項。
0x54 bastroe 將棧頂boolean類型值或byte類型值保存到指定boolean類型數組或byte類型數組的指定項。 0x55 castore 將棧頂char類型值保存到指定char類型數組的指定項。
0x56 sastore 將棧頂short類型值保存到指定short類型數組的指定項。
wide指令
指令碼 操做碼(助記符) 操做數 描述(棧指操做數棧)
0xc4 wide 使用附加字節擴展局部變量索引(iinc指令特殊)。
通用(無類型)棧操做指令
指令碼 操做碼(助記符) 操做數 描述(棧指操做數棧)
0x00 nop 空操做。
0x57 pop 從棧頂彈出一個字長的數據。
0x58 pop2 從棧頂彈出兩個字長的數據。
0x59 dup 複製棧頂一個字長的數據,將複製後的數據壓棧。
0x5a dup_x1 複製棧頂一個字長的數據,彈出棧頂兩個字長數據,先將複製後的數據壓棧,再將彈出的兩個字長數據壓棧。 0x5b dup_x2 複製棧頂一個字長的數據,彈出棧頂三個字長的數據,將複製後的數據壓棧,再將彈出的三個字長的數據壓棧。 0x5c dup2 複製棧頂兩個字長的數據,將複製後的兩個字長的數據壓棧。
0x5d dup2_x1 複製棧頂兩個字長的數據,彈出棧頂三個字長的數據,將複製後的兩個字長的數據壓棧,再將彈出的三個字長的數據壓棧。 0x5e dup2_x2 複製棧頂兩個字長的數據,彈出棧頂四個字長的數據,將複製後的兩個字長的數據壓棧,再將彈出的四個字長的數據壓棧。 0x5f swap 交換棧頂兩個字長的數據的位置。Java指令中沒有提供以兩個字長爲單位的交換指令。
類型轉換指令
指令碼 操做碼(助記符) 操做數 描述(棧指操做數棧)
0x86 i2f 將棧頂int類型值轉換爲float類型值。
0x85 i2l 將棧頂int類型值轉換爲long類型值。
0x87 i2d 將棧頂int類型值轉換爲double類型值。
0x8b f2i 將棧頂float類型值轉換爲int類型值。
0x8c f2l 將棧頂float類型值轉換爲long類型值。
0x8d f2d 將棧頂float類型值轉換爲double類型值。
0x88 l2i 將棧頂long類型值轉換爲int類型值。
0x89 l2f 將棧頂long類型值轉換爲float類型值。
0x8a l2d 將棧頂long類型值轉換double類型值。
0x8e d2i 將棧頂double類型值轉換爲int類型值。
0x90 d2f 將棧頂double類型值轉換爲float類型值。
0x8f d2l 將棧頂double類型值轉換爲long類型值。
0x91 i2b 將棧頂int類型值截斷成byte類型,後帶符號擴展成int類型值入棧。
0x92 i2c 將棧頂int類型值截斷成char類型值,後帶符號擴展成int類型值入棧。
0x93 i2s 將棧頂int類型值截斷成short類型值,後帶符號擴展成int類型值入棧。
整數運算
指令碼 操做碼(助記符) 操做數 描述(棧指操做數棧)
0x60 iadd 將棧頂兩int類型數相加,結果入棧。
0x64 isub 將棧頂兩int類型數相減,結果入棧。
0x68 imul 將棧頂兩int類型數相乘,結果入棧。
0x6c idiv 將棧頂兩int類型數相除,結果入棧。
0x70 irem 將棧頂兩int類型數取模,結果入棧。
0x74 ineg 將棧頂int類型值取負,結果入棧。
0x61 ladd 將棧頂兩long類型數相加,結果入棧。
0x65 lsub 將棧頂兩long類型數相減,結果入棧。
0x69 lmul 將棧頂兩long類型數相乘,結果入棧。
0x6d ldiv 將棧頂兩long類型數相除,結果入棧。
0x71 lrem 將棧頂兩long類型數取模,結果入棧。
0x75 lneg 將棧頂long類型值取負,結果入棧。
0x84 (wide)iinc indexbyte constbyte 將整數值constbyte加到indexbyte指定的int類型的局部變量中。
浮點運算
指令碼 操做碼(助記符) 操做數 描述(棧指操做數棧)
0x62 fadd 將棧頂兩float類型數相加,結果入棧。
0x66 fsub 將棧頂兩float類型數相減,結果入棧。
0x6a fmul 將棧頂兩float類型數相乘,結果入棧。
0x6e fdiv 將棧頂兩float類型數相除,結果入棧。
0x72 frem 將棧頂兩float類型數取模,結果入棧。
0x76 fneg 將棧頂float類型值取反,結果入棧。
0x63 dadd 將棧頂兩double類型數相加,結果入棧。
0x67 dsub 將棧頂兩double類型數相減,結果入棧。
0x6b dmul 將棧頂兩double類型數相乘,結果入棧。
0x6f ddiv 將棧頂兩double類型數相除,結果入棧。
0x73 drem 將棧頂兩double類型數取模,結果入棧。
0x77 dneg 將棧頂double類型值取負,結果入棧。
邏輯運算——移位運算
指令碼 操做碼(助記符) 操做數 描述(棧指操做數棧)
0x78 ishl 左移int類型值。
0x79 lshl 左移long類型值。
0x7a ishr 算術右移int類型值。
0x7b lshr 算術右移long類型值。
0x7c iushr 邏輯右移int類型值。
0x7d lushr 邏輯右移long類型值。
邏輯運算——按位布爾運算
指令碼 操做碼(助記符) 操做數 描述(棧指操做數棧)
0x73 iand 對int類型按位與運算。
0x7f land 對long類型的按位與運算。
0x80 ior 對int類型的按位或運算。
0x81 lor 對long類型的按位或運算。
0x82 ixor 對int類型的按位異或運算。
0x83 lxor 對long類型的按位異或運算。
控制流指令——條件跳轉指令
指令碼 操做碼(助記符) 操做數 描述(棧指操做數棧)
0x99 ifeq branchbyte1 branchbyte2 若棧頂int類型值爲0則跳轉。
0x9a ifne branchbyte1 branchbyte2 若棧頂int類型值不爲0則跳轉。
0x9b iflt branchbyte1 branchbyte2 若棧頂int類型值小於0則跳轉。
0x9e ifle branchbyte1 branchbyte2 若棧頂int類型值小於等於0則跳轉。
0x9d ifgt branchbyte1 branchbyte2 若棧頂int類型值大於0則跳轉。
0x9c ifge branchbyte1 branchbyte2 若棧頂int類型值大於等於0則跳轉。
0x9f if_icmpeq branchbyte1 branchbyte2 若棧頂兩int類型值相等則跳轉。
0xa0 if_icmpne branchbyte1 branchbyte2 若棧頂兩int類型值不相等則跳轉。
0xa1 if_icmplt branchbyte1 branchbyte2 若棧頂兩int類型值前小於後則跳轉。
0xa4 if_icmple branchbyte1 branchbyte2 若棧頂兩int類型值前小於等於後則跳轉。
0xa3 if_icmpgt branchbyte1 branchbyte2 若棧頂兩int類型值前大於後則跳轉。
0xa2 if_icmpge branchbyte1 branchbyte2 若棧頂兩int類型值前大於等於後則跳轉。
0xc6 ifnull branchbyte1 branchbyte2 若棧頂引用值爲null則跳轉。
0xc7 ifnonnull branchbyte1 branchbyte2 若棧頂引用值不爲null則跳轉。
0xa5 if_acmpeq branchbyte1 branchbyte2 若棧頂兩引用類型值相等則跳轉。
0xa6 if_acmpne branchbyte1 branchbyte2 若棧頂兩引用類型值不相等則跳轉。
控制流指令——比較指令
指令碼 操做碼(助記符) 操做數 描述(棧指操做數棧)
0x94 lcmp 比較棧頂兩long類型值,前者大,1入棧;相等,0入棧;後者大,-1入棧。
0x95 fcmpl 比較棧頂兩float類型值,前者大,1入棧;相等,0入棧;後者大,-1入棧;有NaN存在,-1入棧。 0x96 fcmpg 比較棧頂兩float類型值,前者大,1入棧;相等,0入棧;後者大,-1入棧;有NaN存在,-1入棧。 0x97 dcmpl 比較棧頂兩double類型值,前者大,1入棧;相等,0入棧;後者大,-1入棧;有NaN存在,-1入棧。 0x98 dcmpg 比較棧頂兩double類型值,前者大,1入棧;相等,0入棧;後者大,-1入棧;有NaN存在,-1入棧。
控制流指令——無條件跳轉指令
指令碼 操做碼(助記符) 操做數 描述(棧指操做數棧)
0xa7 goto branchbyte1 branchbyte2 無條件跳轉到指定位置。
0xc8 goto_w branchbyte1 branchbyte2 branchbyte3 branchbyte4 無條件跳轉到指定位置(寬索引)。
控制流指令——表跳轉指令
指令碼 操做碼(助記符) 操做數 描述(棧指操做數棧)
0xaa tableswitch <0-3bytepad> defaultbyte1 defaultbyte2 defaultbyte3 defaultbyte4 lowbyte1 lowbyte2 lowbyte3 lowbyte4 highbyte1 highbyte2 highbyte3 highbyte4 jump offsets... 經過索引訪問跳轉表,並跳轉。
0xab lookupswitch <0-3bytepad> defaultbyte1 defaultbyte2 defaultbyte3 defaultbyte4 npairs1 npairs2 npairs3 npairs4 match offsets 經過鍵值訪問跳轉表,並跳轉。
控制流指令——異常和finally
指令碼 操做碼(助記符) 操做數 描述(棧指操做數棧)
0xbf athrow 拋出異常。
0xa8 jsr branchbyte1 branchbyte2 跳轉到子例程序。
0xc9 jsr_w branchbyte1 branchbyte2 branchbyte3 branchbyte4 跳轉到子例程序(寬索引)。
0xa9 (wide)ret indexbyte 返回子例程序。
對象操做指令
指令碼 操做碼(助記符) 操做數 描述(棧指操做數棧)
0xbb new indexbyte1 indexbyte2 建立新的對象實例。
0xc0 checkcast indexbyte1 indexbyte 類型強轉。
0xc1 instanceof indexbyte1 indexbyte2 判斷類型。
0xb4 getfield indexbyte1 indexbyte2 獲取對象字段的值。
0xb5 putfield indexbyte1 indexbyte2 給對象字段賦值。
0xb2 getstatic indexbyte1 indexbyte2 獲取靜態字段的值。
0xb3 putstatic indexbyte1 indexbyte2 給靜態字段賦值。
數組操做指令
指令碼 操做碼(助記符) 操做數 描述(棧指操做數棧)
0xbc newarray atype 建立type類型的數組。
0xbd anewarray indexbyte1 indexbyte2 建立引用類型的數組。
0xbe arraylength 獲取一維數組的長度。
0xc5 multianewarray indexbyte1 indexbyte2 dimension 建立dimension維度的數組。
方法調用指令
指令碼 操做碼(助記符) 操做數 描述(棧指操做數棧)
0xb7 invokespecial indexbyte1 indexbyte2 編譯時方法綁定調用方法。
0xb6 invokevirtual indexbyte1 indexbyte2 運行時方法綁定調用方法。
0xb8 invokestatic indexbyte1 indexbyte2 調用靜態方法。
0xb9 invokeinterface indexbyte1 indexbyte2 count 0 調用接口方法。
方法返回指令
指令碼 操做碼(助記符) 操做數 描述(棧指操做數棧)
0xac ireturn 返回int類型值。
0xad lreturn 返回long類型值。
0xae freturn 返回float類型值。
0xaf dreturn 返回double類型值。
0xb0 areturn 返回引用類型值。
0xb1 return void函數返回。
線程同步指令
指令碼 操做碼(助記符) 操做數 描述(棧指操做數棧)
0xc2 monitorenter 進入並得到對象監視器。
0xc3 monitorexit 釋放並退出對象監視器。
說明:
本文檔虛擬機參數以Hot Spot 64bit/JDK8爲準,不一樣的項目參數可能不一樣,找準適合當前項目的纔是最優的。有不一樣觀點者歡迎指導和交流!!!