使用javap深入理解Java整型常量和整型變數的區別
我下圖程式碼第五行和第九行分別定義了一個整型變數和一個整型常量:
static final int number1 = 512;
static int number3 = 545;
Java程式設計師都知道兩者的區別。
下面我們就用javap將.class檔案反編譯出來然後深入研究Java裡整型變數和整型常量的區別。
使用命令列javap -c constant.ConstantFolding檢視.class檔案反編譯出來的位元組碼:
結果:
這些位元組碼指令的說明,在wikipedia裡有說明:
wiki: https://en.wikipedia.org/wiki/Java_bytecode_instruction_listings
我們們Java程式設計師不需要把它們都背下來,只需要把這個網頁收藏起來,要用的時候當成字典來用就行:
sipush 545: 將整數545放置到棧上
putstatic #16:
將棧上的值545賦給當前類的靜態欄位裡。
那麼putstatic #16裡的#16代表什麼含義?
我們再用javap -v 引數反編譯,就能看到這個類的常量池(Constant pool). 大家看下圖藍色高亮的一行:
constant/ConstantFolding.number3:I
說明#16代表類constant.ConstantFolding的成員number3,型別為I。
至此,這兩行位元組碼指令聯合起來,實際對應了我們寫的Java程式碼:
static int number3 = 545;
我們繼續分析javap反編譯出來的位元組碼。
aload_0: 將序號為0的本地變數的引入載入到棧上
invokespecial: 呼叫物件例項上的成員方法,如果有返回值,方法的返回值儲存到棧上。具體呼叫的方法由#標識,可在常量池中查詢到對應的方法名。
ldc: 將常量池上代號為#<數字>的常量的值從常量池載入到棧上。
我們從下圖的常量池列表能發現,序號為#29的常量318976正是整型常量number1(512)和整型常量(623)的積。由此可以看出, number1 * number2這個表示式,因為參與運算的兩個運算元通過STATIC和FINAL修飾成為了整型常量,因此其積在編譯期就能得到,所以編譯器在編譯時就計算出來,儲存在變數池裡,序號為#29。
那麼整型變數做乘法運算,對應的位元組碼又是什麼樣的呢?
從下圖序號為3的code開始:
getstatic #16: 將類的靜態成員#16載入到棧上。#16對應的成員為number3,值為545。
getstatic #18: 將類的靜態成員#18載入到棧上。#18對應的成員為number4,值為619。
imul: 執行棧上兩個整數的乘法運算。
istore_2: 將結果儲存到區域性變數2裡。
此時,我們Java程式碼裡的int product2 = number3 * number4就執行完了。
大家看到的剩下的藍色位元組碼,都對應了下面這行列印語句。
System.out.println("Value: " + product1 + " , " + product2);
從這些位元組碼也能看出,Java裡我們直接用加號進行字串拼接操作,Java編譯器在編譯時,自動使用了StringBuilder進行優化。
既然整型變數的乘積需要列印出來,因此位元組碼的iload_2將之前用istore_2儲存在區域性變數2中的計算結果又載入到棧上,這樣乘積結果最後就能輸出了。
希望通過這個簡單的例子,大家能學會用javap去深入理解一些Java和JVM的細節
來自 “ ITPUB部落格 ” ,連結:http://blog.itpub.net/24475491/viewspace-2212997/,如需轉載,請註明出處,否則將追究法律責任。
相關文章
- 深入理解 Java 的整型型別:如何實現 2+2=5?Java型別
- 交換兩個整型變數變數
- Java整型資料型別(詳解)Java資料型別
- 什麼是整型型別?Python整型詳細介紹型別Python
- Java隨談(六)## 我們真的理解 Java 裡的整型嗎?Java
- Java工具類 NumberUtils 對整型數字的引用Java
- java常量和變數Java變數
- 二,Java中常量與變數的理解Java變數
- 四:java常量和變數Java變數
- 什麼是整型?Python整型詳細介紹Python
- Python基本資料型別之整型Python資料型別
- 深入理解 Python 虛擬機器:整型(int)的實現原理及原始碼剖析Python虛擬機原始碼
- 深入理解equals和==的區別
- 加了強型別如何將請求引數轉為整型型別
- java變數及常量Java變數
- 正確理解和使用JAVA中的字串常量池Java字串
- 指標常量和常量指標的區別指標
- Python技術分享:深入理解ThreadLocal變數的功能和使用Pythonthread變數
- 【譯】自動生成整型序列
- [譯]BigInt:JavaScript 中的任意精度整型JavaScript
- Spark 外部變數和BroadCast變數的區別Spark變數AST
- Java第三天【變數、常量、資料型別】Java變數資料型別
- 深入理解變數提升和函式提升變數函式
- 深入理解js的變數提升和函式提升JS變數函式
- JAVA基礎04——變數與常量Java變數
- 第八章:變數、常量和基礎型別變數型別
- mssql sqlserver 驗證整型函式分享SQLServer函式
- SMT整型溢位漏洞分析筆記筆記
- 智慧合約安全之整型溢位
- java 全域性變數和區域性變數Java變數
- 深入理解Java中的不可變物件Java物件
- PHP 定義常量 define 和 const的區別PHP
- 成員變數、全域性變數、例項變數、類變數、靜態變數和區域性變數的區別變數
- Go基礎系列:常量和變數Go變數
- 【C語言】給定兩個整型變數的值,將兩個值的內容進行交換C語言變數
- Java基礎06:變數、常量、作用域Java變數
- Java培訓教程分享:變數與常量Java變數
- 修改全域性變數時,可變型別和不可變型別的區別變數型別