深入解析反編譯字節(jié)碼文件中的代碼邏輯JVM中的String操作
主要內(nèi)容
以java程序代碼為起點(diǎn)講解在JVM層面上,搞清楚程序String操作的反編譯字節(jié)碼文件后,都發(fā)生了什么。
StringTable
String s1 = "a"; String s2 = "b"; String s3 = "a" + "b"; String s4 = s1 + s2; String s5 = "ab"; String s6 = s4.intern(); // 問 System.out.println(s3 == s4); System.out.println(s3 == s5); System.out.println(s3 == s6); String x2 = new String("c") + new String("d"); String x1 = "cd"; x2.intern(); // 問,如果調(diào)換了【最后兩行代碼】的位置呢,如果是jdk1.6呢 System.out.println(x1 == x2);
輸出結(jié)果:flase true true flase
至于為什么前先明白StringTable的特性:
- 在JDK1.6以前,StringTable在方法區(qū)和堆空間分離,采用永久代的形式實(shí)現(xiàn),而在JDK1.8及以后,方法區(qū)是由采用本地內(nèi)存,以元空間的形式實(shí)現(xiàn),而此時(shí)StringTable被遷移到了堆空間中(內(nèi)存更加大了)。
- StringTable里面的字符串只有在被第一次使用時(shí)才會(huì)變成對(duì)象,沒被使用依舊是符號(hào)。
- 利用串池的機(jī)制,來避免重復(fù)創(chuàng)建字符串對(duì)象
- 字符串變量拼接的原理是 StringBuilder (1.8)
- 字符串常量拼接的原理是編譯期優(yōu)化
可以使用 intern 方法,主動(dòng)將串池中還沒有的字符串對(duì)象放入串池
- 1.8 將這個(gè)字符串對(duì)象嘗試放入串池,如果有則并不會(huì)放入,如果沒有則放入串池, 會(huì)把串池中的對(duì)象返回
- 1.6 將這個(gè)字符串對(duì)象嘗試放入串池,如果有則并不會(huì)放入,如果沒有會(huì)把此對(duì)象復(fù)制一份,放入串池, 會(huì)把串池中的對(duì)象返回
javap -v 反編譯字節(jié)碼內(nèi)部處理邏輯
下面我將利用javap -v 反編譯該字節(jié)碼,得到代碼內(nèi)部處理邏輯。
依次解釋:
==就是比較兩個(gè)引用的內(nèi)存地址是否相同。
第一個(gè)false:
s3在編譯期間就優(yōu)化成了字符串常量"ab",在StringTable中,而s4則調(diào)用了StringBuilder中的append方法,是s1,s2都是new出來的,最后相當(dāng) StringBulder s=new StringBulder();然后s.append("a").append("b");
然后把s的引用給了s4,所以s4是在堆的其他地方,不在常量池中。所以false。
第二個(gè)true:
正如前面所說,編譯器在編譯階段就已經(jīng)將"a"+"b"優(yōu)化成了"ab"(語法糖)因?yàn)?quot;a","b"都是常量,所以沒有問題。所以說s3和s5內(nèi)存地址相等,都在常量池里面。
第三個(gè)true:
因?yàn)镾tringTable特性,s4調(diào)用intern方法準(zhǔn)備將自己的字符串入池,而此時(shí)發(fā)現(xiàn)池中有"ab",s4在入池前就有了,所以s4入池失敗,但是返回的還是是池中的引用對(duì)象地址。ps:如果此時(shí)池中沒有"ab",那么s4可以入池成功,并且自己的地址也變成了常量池中對(duì)應(yīng)的串地址(jdk1.8以后才行)
第四個(gè)false:
與前面3類似,在x2入池前,常量池中已經(jīng)有了"cd",所以入池失敗,自己還是原來的地址(堆的其他位置),與常量池地址不同。所以按照注釋:如果【調(diào)換最后兩行代碼】,則入池成功,x2也變成了池中的地址此時(shí)為true(jdk1.8以后才行),如果是jdk1.6及以前,是采用復(fù)制一個(gè)對(duì)象,比如x3然后入池,x2還是沒有改變地址。
以上就是深入解析反編譯字節(jié)碼文件中的代碼邏輯JVM中的String操作的詳細(xì)內(nèi)容,更多關(guān)于JVM中 String操作反編譯字節(jié)碼的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
解析Spring Boot 如何讓你的 bean 在其他 bean&n
在 SpringBoot 中如何讓自己的某個(gè)指定的 Bean 在其他 Bean 前完成被 Spring 加載?我聽到這個(gè)問題的第一反應(yīng)是,為什么會(huì)有這樣奇怪的需求?下面小編給大家分析下Spring Boot 如何讓你的 bean 在其他 bean 之前完成加載 ,感興趣的朋友一起看看吧2024-01-01Spring Boot不同版本Redis設(shè)置JedisConnectionFactory詳解
本文章向大家介紹Spring Boot不同版本Redis設(shè)置JedisConnectionFactory,主要內(nèi)容包括1.X 版本、2.X 版本、2.、基本概念、基礎(chǔ)應(yīng)用、原理機(jī)制和需要注意的事項(xiàng)等,并結(jié)合實(shí)例形式分析了其使用技巧,希望通過本文能幫助到大家理解應(yīng)用這部分內(nèi)容2023-09-09Spring MVC中使用Controller如何進(jìn)行重定向
這篇文章主要介紹了Spring MVC中使用Controller如何進(jìn)行重定向操作,具有很好的參考價(jià)值,希望對(duì)大家有所幫助。如有錯(cuò)誤或未考慮完全的地方,望不吝賜教2021-09-09使用mybatis切片實(shí)現(xiàn)數(shù)據(jù)權(quán)限控制的操作流程
數(shù)據(jù)權(quán)限控制需要對(duì)查詢出的數(shù)據(jù)進(jìn)行篩選,對(duì)業(yè)務(wù)入侵最少的方式就是利用mybatis或者數(shù)據(jù)庫連接池的切片對(duì)已有業(yè)務(wù)的sql進(jìn)行修改,本文給大家介紹了使用mybatis切片實(shí)現(xiàn)數(shù)據(jù)權(quán)限控制的操作流程,需要的朋友可以參考下2024-07-07Java?將HTML轉(zhuǎn)為XML的詳細(xì)步驟
這篇文章主要介紹了Java?將HTML轉(zhuǎn)為XML,本文將以html轉(zhuǎn)為xml格式為例,介紹如何實(shí)現(xiàn)轉(zhuǎn)換,以下是詳細(xì)方法及步驟,需要的朋友可以參考下2022-06-06SpringBoot實(shí)現(xiàn)登錄攔截器的方法詳解
其實(shí)spring?boot攔截器的配置方式和springMVC差不多,只有一些小的改變需要注意下就ok了。本文主要給大家介紹了關(guān)于如何在Springboot實(shí)現(xiàn)登陸攔截器功能,需要的朋友可以參考下2022-07-07