前言
站在用戶的角度思考問題,與客戶深入溝通,找到霍山網(wǎng)站設(shè)計(jì)與霍山網(wǎng)站推廣的解決方案,憑借多年的經(jīng)驗(yàn),讓設(shè)計(jì)與互聯(lián)網(wǎng)技術(shù)結(jié)合,創(chuàng)造個(gè)性化、用戶體驗(yàn)好的作品,建站類型包括:成都網(wǎng)站建設(shè)、做網(wǎng)站、企業(yè)官網(wǎng)、英文網(wǎng)站、手機(jī)端網(wǎng)站、網(wǎng)站推廣、域名注冊(cè)、網(wǎng)頁空間、企業(yè)郵箱。業(yè)務(wù)覆蓋霍山地區(qū)。
在實(shí)際中,Java程序中的對(duì)象或許 本身就是逃逸 的,或許因?yàn)?方法內(nèi)聯(lián)不夠徹底 而被即時(shí)編譯器 當(dāng)成是逃逸 的,這兩種情況都將
導(dǎo)致即時(shí)編譯器 無法進(jìn)行標(biāo)量替換 ,這時(shí),針對(duì)對(duì)象字段訪問的優(yōu)化顯得更為重要。
static int bar(Foo o, int x) { o.a = x; return o.a; }
static int bar(Foo o, int x) { o.a = x; return x; }
即時(shí)編譯器也能作出類似的 自動(dòng)優(yōu)化
字段讀取優(yōu)化
即時(shí)編譯器會(huì)優(yōu)化 實(shí)例字段 和 靜態(tài)字段 的訪問,以 減少總的內(nèi)存訪問次數(shù)
即時(shí)編譯器將 沿著控制流 ,緩存各個(gè)字段 存儲(chǔ)節(jié)點(diǎn) 將要存儲(chǔ)的值,或者字段 讀取節(jié)點(diǎn) 所得到的值
樣例1
static int bar(Foo o, int x) { int y = o.a + x; return o.a + y; }
實(shí)例字段Foo.a被讀取兩次,即時(shí)編譯器會(huì)將第一次讀取的值緩存起來,并且 替換 第二次的字段讀取操作,以 節(jié)省 一次內(nèi)存訪問
static int bar(Foo o, int x) { int t = o.a; int y = t + x; return t + y; }
樣例2
static int bar(Foo o, int x) { o.a = 1; if (o.a >= 0) return x; else return -x; }
字段讀取節(jié)點(diǎn)被替換成一個(gè) 常量 ,進(jìn)一步觸發(fā)更多的優(yōu)化
static int bar(Foo o, int x) { o.a = 1; return x; }
樣例3
class Foo { boolean a; void bar() { a = true; while (a) {} } void whatever() { a = false; } }
即時(shí)編譯器會(huì)將while循環(huán)中讀取實(shí)例字段a的操作 直接替換為常量true
void bar() { a = true; while (true) {} } // 生成的機(jī)器碼將陷入這一死循環(huán)中 0x066b: mov r11,QWORD PTR [r15+0x70] // 安全點(diǎn)測(cè)試 0x066f: test DWORD PTR [r11],eax // 安全點(diǎn)測(cè)試 0x0672: jmp 0x066b // while (true)
1、可以通過 volatile 關(guān)鍵字標(biāo)記實(shí)例字段a,以 強(qiáng)制 對(duì)a的讀取
2、實(shí)際上,即時(shí)編譯器將 在volatile字段訪問前后插入內(nèi)存屏障節(jié)點(diǎn)
3、同理, 加解鎖操作同樣也會(huì)阻止即時(shí)編譯器的字段讀取優(yōu)化
字段存儲(chǔ)優(yōu)化
如果一個(gè)字段先后被存儲(chǔ)了兩次,而且這 兩次存儲(chǔ)之間沒有對(duì)第一次存儲(chǔ)內(nèi)容讀取 ,那么即時(shí)編譯器將 消除 第一個(gè)字段存儲(chǔ)
樣例1
class Foo { int a = 0; void bar() { a = 1; a = 2; } }
即時(shí)編譯器將消除bar方法的冗余存儲(chǔ)
void bar() { a = 2; }
樣例2
即便在某個(gè)字段的兩個(gè)存儲(chǔ)操作之間讀取該字段,即時(shí)編譯器也可能在 字段讀取優(yōu)化 的幫助下,將第一個(gè)存儲(chǔ)操作當(dāng)作 冗余存儲(chǔ)
場(chǎng)景:例如兩個(gè)存儲(chǔ)操作之間隔著許多代碼,又或者因?yàn)?方法內(nèi)聯(lián) 的原因,將兩個(gè)存儲(chǔ)操作納入到同一編譯單元里(如構(gòu)造器中字段的初始化以及隨后的更新)
class Foo { int a = 0; void bar() { a = 1; int t = a; a = t + 2; } } // 優(yōu)化為 class Foo { int a = 0; void bar() { a = 1; int t = 1; a = t + 2; } } // 進(jìn)一步優(yōu)化為 class Foo { int a = 0; void bar() { a = 3; } }
如果所存儲(chǔ)的字段被標(biāo)記為 volatile ,那么即時(shí)編譯器也 不能消除冗余存儲(chǔ)
死代碼消除
樣例1
int bar(int x, int y) { int t = x*y; t = x+y; return t; }
沒有節(jié)點(diǎn)依賴于t的第一個(gè)值 x*y ,因此該乘法運(yùn)算將被消除
int bar(int x, int y) { return x+y; }
樣例2
int bar(boolean f, int x, int y) { int t = x*y; if (f) t = x+y; return t; }
部分程序路徑上有冗余存儲(chǔ)(f=true),該路徑上的乘法運(yùn)算將會(huì)被消除
int bar(boolean f, int x, int y) { int t; if (f) t = x+y; else t = x*y; return t; }
樣例3
int bar(int x) { if (false) return x; else return -x; }
不可達(dá)分支指的是任何程序路徑都不可達(dá)到的分支,即時(shí)編譯器將 消除不可達(dá)分支
int bar(int x) { return -x; }
總結(jié)
以上就是這篇文章的全部內(nèi)容了,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,如果有疑問大家可以留言交流,謝謝大家對(duì)創(chuàng)新互聯(lián)的支持。
網(wǎng)站欄目:JVM進(jìn)階教程之字段訪問優(yōu)化淺析
網(wǎng)站鏈接:http://muchs.cn/article2/gedooc.html
成都網(wǎng)站建設(shè)公司_創(chuàng)新互聯(lián),為您提供網(wǎng)站設(shè)計(jì)公司、域名注冊(cè)、網(wǎng)站策劃、Google、品牌網(wǎng)站設(shè)計(jì)、網(wǎng)站維護(hù)
聲明:本網(wǎng)站發(fā)布的內(nèi)容(圖片、視頻和文字)以用戶投稿、用戶轉(zhuǎn)載內(nèi)容為主,如果涉及侵權(quán)請(qǐng)盡快告知,我們將會(huì)在第一時(shí)間刪除。文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如需處理請(qǐng)聯(lián)系客服。電話:028-86922220;郵箱:631063699@qq.com。內(nèi)容未經(jīng)允許不得轉(zhuǎn)載,或轉(zhuǎn)載時(shí)需注明來源: 創(chuàng)新互聯(lián)