【jvm】字符串常量池問題

目錄

        • 一、基本概念
          • 1.1 說明
          • 1.2 特點
        • 二、存放位置
          • 2.1 JDK1.6及以前
          • 2.2 JDK1.7
          • 2.3 JDK1.8及以后
        • 三、工作原理
          • 3.1 創建字符串常量
          • 3.2 使用new關鍵字創建字符串
        • 四、intern()方法
          • 4.1 作用
        • 五、優點
        • 六、字節碼分析
          • 6.1 示例1
            • 6.1.1 代碼示例
            • 6.1.2 字節碼
            • 6.1.3 解析
          • 6.2 示例2
            • 6.2.1 代碼示例
            • 6.2.2 分析(jdk8)
          • 6.3 示例3
            • 6.3.1 代碼示例
            • 6.2.2 分析(jdk8)

一、基本概念
1.1 說明
  • 1.JVM字符串常量池是Java虛擬機(JVM)中一個特殊的內存區域。
  • 2.JVM字符串常量池用于存儲字符串常量。
  • 3.提高性能和減少內存開銷。
  • 4.字符串常量池是JVM用于存儲字符串常量的一個內存區域,避免了相同字符串的重復創建,節省內存空間。
1.2 特點
  • 1.字符串常量池中的字符串對象是不可變的。
  • 2.相同的字符串常量在池中只存儲一份,通過引用共享。
二、存放位置
2.1 JDK1.6及以前
  • 1.字符串常量池存放在永久代中,永久代是非堆內存的一部分,用于存儲類的元數據、常量、靜態變量等。
2.2 JDK1.7
  • 1.字符串常量池從永久代移動到了Java堆中,而運行時常量池保留在永久代中。
  • 2.這一變化為了適應永久代內存限制問題,并提升性能。
2.3 JDK1.8及以后
  • 1.永久代被移除,取而代之的是元空間,字符串常量池仍然位于Java堆中。
  • 2.運行時常量池被移動到元空間。
三、工作原理
3.1 創建字符串常量
  • 1.使用雙引號創建字符串時(String a = “123”; ),JVM會首先在字符串常量池中查找是否已存在該字符串。
  • 2.如果存在,則直接返回池中該字符串的引用。
  • 3.如果不存在,則在常量池中創建該字符串的實例,并返回其引用。
3.2 使用new關鍵字創建字符串
  • 1.使用new關鍵字創建字符串對象(如String str = new String(“abc”);)時,JVM會在堆內存中創建一個新的字符串對象,而不管字符串常量池中是否已存在相同的字符串。
  • 2.如果需要,可以通過調用intern()方法將新創建的字符串對象放入常量池中。
四、intern()方法
4.1 作用
  • 1.intern()方法是String類的一個本地方法。
  • 2.用于將字符串對象添加到字符串常量池中。
  • 3.如果常量池中已經包含了一個等于此String對象的字符串(使用equals(Object)方法確定),則返回代表池中這個字符串的String對象的引用。
  • 4.否則,將此String對象包含的字符串添加到常量池中,并返回此String對象的引用。
五、優點
  • 1.節省內存:通過共享相同的字符串常量,避免了不必要的重復創建。
  • 2.提高性能:減少了對象創建和垃圾回收的開銷。
  • 3.簡化字符串比較:由于字符串常量池中的字符串是唯一的,可以使用==操作符來比較字符串的引用,從而簡化比較操作。
六、字節碼分析
6.1 示例1
6.1.1 代碼示例
@Test
public void test(){String str1 = new String("hello") + new String("world");String str2 = "helloworld";System.out.println(str1 == str2);
}
6.1.2 字節碼
 0 new #2 <java/lang/StringBuilder>3 dup4 invokespecial #3 <java/lang/StringBuilder.<init> : ()V>7 new #4 <java/lang/String>
10 dup
11 ldc #5 <hello>
13 invokespecial #6 <java/lang/String.<init> : (Ljava/lang/String;)V>
16 invokevirtual #7 <java/lang/StringBuilder.append : (Ljava/lang/String;)Ljava/lang/StringBuilder;>
19 new #4 <java/lang/String>
22 dup
23 ldc #8 <world>
25 invokespecial #6 <java/lang/String.<init> : (Ljava/lang/String;)V>
28 invokevirtual #7 <java/lang/StringBuilder.append : (Ljava/lang/String;)Ljava/lang/StringBuilder;>
31 invokevirtual #9 <java/lang/StringBuilder.toString : ()Ljava/lang/String;>
34 astore_1
35 ldc #10 <helloworld>
37 astore_2
38 getstatic #11 <java/lang/System.out : Ljava/io/PrintStream;>
41 aload_1
42 aload_2
43 if_acmpne 50 (+7)
46 iconst_1
47 goto 51 (+4)
50 iconst_0
51 invokevirtual #12 <java/io/PrintStream.println : (Z)V>
54 return
6.1.3 解析
  • 1. 0 new #2 <java/lang/StringBuilder>: 調用StringBuilder的new方法
  • 2. 3 dup:復制操作數棧棧頂的一個字(通常是對象引用或數據類型值),并將這個字重新壓入棧頂。
  • 3. 4 invokespecial #3 <java/lang/StringBuilder. : ()V>:執行StringBuilder的初始化方法,會消耗操作數棧頂一個字。
  • 4. 7 new #4 <java/lang/String>:new一個String對象,對象的引用壓入操作數棧。
  • 5. 10 dup:復制操作數棧棧頂的一個字(通常是對象引用或數據類型值),并將這個字重新壓入棧頂。
  • 6. 11 ldc #5 :加載棧頂的一個字,即hello。
  • 7. 13 invokespecial #6 <java/lang/String. : (Ljava/lang/String;)V>:初始化String,消耗一個string對象的引用和復制的字。
  • 8. 16 invokevirtual #7 <java/lang/StringBuilder.append : (Ljava/lang/String;)Ljava/lang/StringBuilder;> : append操作,將hello追加進來。
  • 9. 19 new #4 <java/lang/String> : new一個String對象,對象的引用壓入操作數棧。
  • 10. 22 dup:復制操作數棧棧頂的一個字(通常是對象引用或數據類型值),并將這個字重新壓入棧頂。
  • 11. 23 ldc #8 : 加載棧頂的一個字,即world。
  • 12. 25 invokespecial #6 <java/lang/String. : (Ljava/lang/String;)V>:初始化String,消耗一個string對象的引用和復制的字。
  • 13. 28 invokevirtual #7 <java/lang/StringBuilder.append : (Ljava/lang/String;)Ljava/lang/StringBuilder;>: append操作,將world追加進來。
  • 14. 31 invokevirtual #9 <java/lang/StringBuilder.toString : ()Ljava/lang/String;> :調用StringBuilder的toString方法
  • 15. StringBuilder的toString方法中是直接new了一個String對象。
  • 16. 而String str2 = “helloworld”;是常量池的引用。
  • 17. 因此不是同一個內存地址,所以結果是false。
6.2 示例2
6.2.1 代碼示例
	@Testpublic void test(){String str1 = new String("hello") + new String("world");str1.intern();String str2 = "helloworld";System.out.println(str1 == str2);}
6.2.2 分析(jdk8)
  • 1.str1是直接new了一個對象,執行intern()方法后,將字符串對象添加到字符串常量池中。
  • 2.String str2 = “helloworld”;會先在字符串常量池中找是否有,如果有則返回其對象的引用。
  • 3.所以結果是true。
6.3 示例3
6.3.1 代碼示例
	@Testpublic void test(){String str1 = new String("helloworld") ;String str2 = "helloworld";String intern = str1.intern();System.out.println(str1 == str2);System.out.println(str1 == intern);System.out.println(str2 == intern);}
6.2.2 分析(jdk8)
  • 1.str1在堆上new了一個string對象。
  • 2.str2是將字面量“helloworld”放入字符串常量池中。
  • 3.str1調用intern方法,判斷字符串常量池中有沒有helloworld,發現有,返回了該字符串常量池的引用即str2。
  • 4.此時str1不等于str2。str2和intern是相等的。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/44636.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/44636.shtml
英文地址,請注明出處:http://en.pswp.cn/web/44636.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

STM32智能倉儲管理系統教程

目錄 引言環境準備晶智能倉儲管理系統基礎代碼實現&#xff1a;實現智能倉儲管理系統 4.1 數據采集模塊 4.2 數據處理與決策模塊 4.3 通信與網絡系統實現 4.4 用戶界面與數據可視化應用場景&#xff1a;倉儲管理與優化問題解決方案與優化收尾與總結 1. 引言 智能倉儲管理系統…

7 月12日學習打卡--棧和隊列的相互轉換

hello大家好呀&#xff0c;本博客目的在于記錄暑假學習打卡&#xff0c;后續會整理成一個專欄&#xff0c;主要打算在暑假學習完數據結構&#xff0c;因此會發一些相關的數據結構實現的博客和一些刷的題&#xff0c;個人學習使用&#xff0c;也希望大家多多支持&#xff0c;有不…

什么是STM32?嵌入式和STM32簡單介紹

1、嵌入式和STM32 1.1.什么是嵌入式 除了桌面PC之外&#xff0c;所有的控制類設備都是嵌入式 嵌入式系統的定義&#xff1a;“用于控制、監視或者輔助操作機器和設備的裝置”。 嵌入式系統是一個控制程序存儲在ROM中的嵌入式處理器控制板&#xff0c;是一種專用的計算機系統。…

初階數據結構速成

本篇文章算是對初階數據結構的總結&#xff0c;內容較多&#xff0c;請耐心觀看 基礎概念部分 順序表 線性表&#xff08; linear list &#xff09;是n個具有相同特性的數據元素的有限序列。 線性表是?種在實際中?泛使 ?的數據結構&#xff0c;常?的線性表&#xff1a;…

C語言 錯題本

C語言 錯題本 文章目錄 C語言 錯題本77月11號整數求逆--掌握 7月12號求符合給定條件的整數集水仙花數打印九九口訣表--掌握統計素數并求和--掌握 7月13號湊硬幣前n項和(一加一減)最大公約數 7月14號正序整數分解 7月17號簡單計算器 217月26號求符合給定條件的整數集水仙花數 旨…

【安全設備】上網行為管理

一、什么是上網行為管理 上網行為管理是對企業內部員工使用互聯網行為的監視和管理&#xff0c;旨在規范網絡使用者的上網行為&#xff0c;提高網絡安全性&#xff0c;保護企業信息安全&#xff0c;同時提高員工的工作效率。上網行為管理通過對員工的上網行為進行監控、記錄和…

機器學習——關于極大似然估計法的一些個人思考(通俗易懂極簡版)

最近在回顧機器學習的一些相關理論知識&#xff0c;回顧到極大似然法時&#xff0c;對于極大似然法中的一些公式有些迷糊了&#xff0c;所以本文主要想記錄并分享一下個人關于極大似然估計法的一些思考&#xff0c;如果有誤&#xff0c;請見諒&#xff0c;歡迎一起前來探討。當…

單元測試實施最佳方案(背景、實施、覆蓋率統計)

1. 什么是單元測試&#xff1f; 對于很多開發人員來說&#xff0c;單元測試一定不陌生 單元測試是白盒測試的一種形式&#xff0c;它的目標是測試軟件的最小單元——函數、方法或類。單元測試的主要目的是驗證代碼的正確性&#xff0c;以確保每個單元按照預期執行。單元測試通…

合肥高校大學智能制造實驗室數字孿生可視化系統平臺建設項目驗收

合肥高校大學智能制造實驗室近日迎來了一項重要時刻&#xff0c;數字孿生可視化系統平臺建設項目順利通過了驗收。這一項目的成功實施&#xff0c;不僅標志著合肥高校在智能制造領域取得新的突破&#xff0c;為我國智能制造技術的發展注入新活力。 合肥高校智能制造實驗室作為…

T972 切換至pdm 聲音輸入的方法

1.在hardware/amlogic/audio/audio_hal/audio_hw.c下&#xff0c;直接切換 在 static unsigned int select_port_by_device(struct aml_audio_device *adev) 中先強制切換為pdm 2.在device mk 配置文件中 #add fof fix the mic bug by jason 20230621 PRODUCT_PROPERTY_OVE…

MySQL 數據庫基礎概念

一、什么是數據庫&#xff1f; 數據庫&#xff08;Database&#xff09;是按照數據結構來組織、存儲和管理數據的倉庫。 每個數據庫都有一個或多個不同的 API 用于創建&#xff0c;訪問&#xff0c;管理&#xff0c;搜索和復制所保存的數據。 我們也可以將數據存儲在文件中&…

淺析Kafka Streams中KTable.aggregate()方法的使用

KTable.aggregate() 方法是 Apache Kafka Streams API 中用于對流數據進行狀態化聚合的核心方法之一。這個方法允許你根據一個鍵值&#xff08;通常是<K,V>類型&#xff09;的流數據&#xff0c;應用一個初始值和一個聚合函數&#xff0c;來累積和更新一個狀態&#xff0…

MSPM0G3507(三十六)——超聲波PID控制小車固定距離

效果圖&#xff1a; 波形圖軟件是VOFA&#xff0c;B站有教程 &#xff0c;雖然有缺點但是非常簡單。 視頻效果&#xff1a; PID控制距離 之前發過只有超聲波測距的代碼&#xff0c;MSPM0G3507&#xff08;三十二&#xff09;——超聲波模塊移植代碼-CSDN博客 SYSCFG配置&#…

Ubuntu下如何設置程序include搜索路徑及鏈接路徑

添加庫的include及lib路徑 linux下系統默認路徑為 /usr/include, /usr/local/include, gcc在編譯程序時會按照當前目錄路徑->系統默認路徑->系統環境變量的路徑方式去查找&#xff0c;所以當我們想調用的庫未安裝在系統默認路徑時&#xff0c;我們可以通過手動添加環境變…

數據壓縮的藝術:Kylin Cube設計中的自動壓縮特性

數據壓縮的藝術&#xff1a;Kylin Cube設計中的自動壓縮特性 在大數據的浩瀚宇宙中&#xff0c;Apache Kylin以其卓越的數據立方體&#xff08;Cube&#xff09;技術&#xff0c;為企業提供快速的多維數據分析能力。隨著數據量的不斷增長&#xff0c;存儲效率成為了一個關鍵問…

用友NC Cloud blobRefClassSearch FastJson反序列化RCE漏洞復現

0x01 產品簡介 用友 NC Cloud 是一種商業級的企業資源規劃云平臺,為企業提供全面的管理解決方案,包括財務管理、采購管理、銷售管理、人力資源管理等功能,實現企業的數字化轉型和業務流程優化。 0x02 漏洞概述 用友 NC Cloud blobRefClassSearch 接口處存在FastJson反序列…

開源PHP論壇HadSky本地部署與配置公網地址實現遠程訪問

文章目錄 前言1. 網站搭建1.1 網頁下載和安裝1.2 網頁測試1.3 cpolar的安裝和注冊 2. 本地網頁發布2.1 Cpolar臨時數據隧道2.2 Cpolar穩定隧道&#xff08;云端設置&#xff09;2.3 Cpolar穩定隧道&#xff08;本地設置&#xff09;2.4 公網訪問測試 總結 前言 今天和大家分享…

idea啟動ssm項目詳細教程

前言 今天碰到一個ssm的上古項目&#xff0c;項目沒有使用內置的tomcat作為服務器容器&#xff0c;這個時候就需要自己單獨設置tomcat容器。這讓我想起了我剛入行時被外置tomcat配置支配的恐懼。現在我打算記錄一下配置的過程&#xff0c;希望對后面的小伙伴有所幫助吧。 要求…

什么是計算機數據結構的字典

字典數據結構在計算機編程領域中是一個非常重要且常用的數據結構。它也被稱為關聯數組、哈希表或映射&#xff08;Map&#xff09;&#xff0c;在不同編程語言中有不同的實現和稱呼&#xff0c;但其核心概念和用途大致相同。 字典數據結構是一種鍵值對&#xff08;key-value p…

Linux 軟件工具安裝

Linux 軟件包管理器 yum 什么是軟件包 在Linux下安裝軟件&#xff0c; 一個通常的辦法是下載到程序的源代碼&#xff0c; 并進行編譯&#xff0c;得到可執行程序。 但是這樣太麻煩了&#xff0c; 于是有些人把一些常用的軟件提前編譯好&#xff0c;做成軟件包(可以理解成wind…