(a+b)*10,10是存在哪里的?是常量池么?
今天看到一個很有意思的提問:(a+b)*10,10是存放在哪里的?是常量池么?如果是常量池,在進行運算的時候,是通過指針來找到的吧?
某回答:10是在常量池,常量池在jdk1.8以后已經移到元空間了。
要驗證這個答案是否正確其實很簡單,寫一個測試方法通過javap查看編譯后的字節碼指令就能得出結論。
測試方法源碼如下:
- private int m(int a, int b) {
- int r = a * b * 10;
- return r;
- }
使用javap查看編譯后的字節碼如下:
- private int m(int, int);
- descriptor: (II)I
- flags: ACC_PRIVATE
- Code:
- stack=2, locals=4, args_size=3
- 0: iload_1
- 1: iload_2
- 2: imul
- 3: bipush 10
- 5: imul
- 6: istore_3
- 7: iload_3
- 8: ireturn
筆者翻閱了一下JVM字節碼指令表,相關指令如下圖所示。
字節碼指令由操作碼和零個或多個操作數組成,編譯后會被寫入方法的Code屬性中,操作數要么是立即數,要么是指向class文件結構常量池中常量的索引,要么是跳轉目標指令的偏移量。
設立即數10為x,可得出以下結論:
當x取值在區間[-1,5]時,x直接被編譯進方法的code屬性中,作為iconst指令的操作數;
當x取值在區間[-128,127]時,x也直接被編譯進方法的code屬性中,作為bipush指令的操作數,取值范圍[-128,127]是因為bipush指令的操作數只能是一個字節;
當x取值在區間[-32768,32767]時,x也直接被編譯進方法的code屬性中,作為sipush指令的操作數,取值范圍[-32768,32767]是因為sipush指令的操作數有兩個字節;
否則才會將x編譯進class的常量池,在進行運算時通過ldc指令從常量池(元空間)push進操作數棧中。
本文轉載自微信公眾號「Java藝術」,可以通過以下二維碼關注。轉載本文請聯系Java藝術公眾號。



























