(a+b)*10,10是存在哪里的?是常量池么?
今天看到一個很有意思的提問:(a+b)*10,10是存放在哪里的?是常量池么?如果是常量池,在進(jìn)行運算的時候,是通過指針來找到的吧?
某回答:10是在常量池,常量池在jdk1.8以后已經(jīng)移到元空間了。
要驗證這個答案是否正確其實很簡單,寫一個測試方法通過javap查看編譯后的字節(jié)碼指令就能得出結(jié)論。
測試方法源碼如下:
- private int m(int a, int b) {
- int r = a * b * 10;
- return r;
- }
使用javap查看編譯后的字節(jié)碼如下:
- 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字節(jié)碼指令表,相關(guān)指令如下圖所示。
字節(jié)碼指令由操作碼和零個或多個操作數(shù)組成,編譯后會被寫入方法的Code屬性中,操作數(shù)要么是立即數(shù),要么是指向class文件結(jié)構(gòu)常量池中常量的索引,要么是跳轉(zhuǎn)目標(biāo)指令的偏移量。
設(shè)立即數(shù)10為x,可得出以下結(jié)論:
當(dāng)x取值在區(qū)間[-1,5]時,x直接被編譯進(jìn)方法的code屬性中,作為iconst指令的操作數(shù);
當(dāng)x取值在區(qū)間[-128,127]時,x也直接被編譯進(jìn)方法的code屬性中,作為bipush指令的操作數(shù),取值范圍[-128,127]是因為bipush指令的操作數(shù)只能是一個字節(jié);
當(dāng)x取值在區(qū)間[-32768,32767]時,x也直接被編譯進(jìn)方法的code屬性中,作為sipush指令的操作數(shù),取值范圍[-32768,32767]是因為sipush指令的操作數(shù)有兩個字節(jié);
否則才會將x編譯進(jìn)class的常量池,在進(jìn)行運算時通過ldc指令從常量池(元空間)push進(jìn)操作數(shù)棧中。
本文轉(zhuǎn)載自微信公眾號「Java藝術(shù)」,可以通過以下二維碼關(guān)注。轉(zhuǎn)載本文請聯(lián)系Java藝術(shù)公眾號。