class常量池、運行時常量池和字符串常量池的關系

類常量池、運行時常量池和字符串常量池這三種常量池,在Java中扮演著不同但又相互關聯的角色。理解它們之間的關系,有助于深入理解Java虛擬機(JVM)的內部工作機制,尤其是在類加載、內存分配和字符串處理方面。

類常量池(Class Constant Pool)

每個Java類文件(.class文件)都具有自己的類常量池,它用于存儲編譯期生成的常量,包括各種字面量(字面量就是指由字母、數字等構成的字符串或者數值)和符號引用(比如類和接口的全名、字段的名稱和描述符、方法的名稱和描述符)。類常量池在編譯期間就已經被確定,并被保存在.class文件中。

Class常量池是用來保存常量的一個中間場所。在JVM真的運行時,需要把類常量池中的常量加載到內存中的運行時常量池中。

運行時常量池(Runtime Constant Pool)

運行時常量池是類被加載到JVM時類常量池的內存版本:當Java類被加載到JVM時,各個類文件中的類常量池內容被讀取并存入到運行時常量池中,其中字符串的部分直接進到字符串池,其他常量進入到運行時常量池。

根據Java虛擬機規范約定:每一個運行時常量池都在Java虛擬機的方法區中分配,在加載類和接口到虛擬機后,就創建對應的運行時常量池。

規范中規定了運行時常量池屬于方法區,但是沒規定方法區屬于哪。于是虛擬機在各自實現的時候就各顯神通了。在不同版本的JDK中,運行時常量池所處的位置也不一樣。以HotSpot虛擬機為例:

在JDK 1.7之前,方法區位于永久代,運行時常量池作為方法區的一部分,處于永久代中,字符串常量池位于運行時常量池的一部分也處于永久代中。

jdk1.7之間jvm內存結構
因為使用永久代實現方法區可能導致內存泄露問題,所以,從JDK1.7開始,JVM嘗試解決這一問題。

在JDK 1.7中,靜態變量和運行時常量池中的字符串常量池轉移到了堆內存中,其他類型的常量還保留在方法區中。
在這里插入圖片描述
在JDK 1.8中,徹底移除了永久代,方法區通過元空間的方式實現,元空間是使用本地內存(Native Memory)來存儲類的元數據信息的。隨之,運行時常量池也在元空間中實現。
在這里插入圖片描述

運行時常量池中包含了若干種不同的常量,他的來源主要有兩種:

  • 編譯期可知的字面量和符號引用(來自Class常量池)

  • 運行期解析后可獲得的常量(如String的intern方法)

字符串常量池(String Constant Pool)

字符串常量池專門用于存儲字符串常量。對于 Hotspot 虛擬機來說,類加載時,字符串字面量作為類常量池的一部分信息被載入運行時常量池中,它們以特殊的形式存儲在運行時常量池中,此時它們并未被實例化為Java堆中的String對象。只有當這個字符串字面量被調用時,才會對其進行解析,即檢查字符串常量池中是否已經存在相同內容的字符串對象。如果存在,就直接返回指向該對象的引用,如果不存在,虛擬機會在字符串常量池中創建一個對應的String實例,并返回這個新實例的引用。

這種處理方式的優勢在于,可以減少在類加載階段對內存的需求和降低開銷,因為不是所有的字符串字面量在類的使用周期內都會被用到。同時,此方法延遲了String對象的實例化,直到它們真正被需要,這有助于提高性能并減少內存的無謂占用。

為什么從JDK 1.7開始,字符串常量池從永久代中挪到堆(Heap)中?

主要原因是因為永久代的 GC 回收效率太低,只有在FulIGC的時候才會被執行回收。但是Java中往往會有很多字符串的生命周期都很短暫,將字符串常量池放到堆中,能夠更高效及時地回收字符串內存。

字符串常量池中的常量有以下幾個來源:
1、字面量常量。
在代碼中直接使用雙引號括起來的字符串字面值(如 strings="hello”)會被認為是常量,并且會在編譯后進入class文件的常量池,并且在運行階段,進入字符串常量池。這是最常見的字符串常量來源。
2、intern()方法
String類提供了一個intern方法,用于將字符串對象手動添加到字符串常量池中。調用intern()方法時,如果字符串常量池中已經存在相同內容的字符串,將會返回常量池中的引用;如果不存在,則會在常量池中添加該字符串在堆中的引用。

要注意的是,字符串常量池是一個固定大小的Hashtable,默認值大小長度是1009,如果放進字符串常量池的String非常多,就會造成Hash沖突嚴重,從而導致鏈表會很長,而鏈表長了后直接會造成的影響就是當調用String.intern時性能會大幅下降(因為要一個一個找,以此判斷字符串常量在不在字符串常量池中)。在jdk6中StringTable是固定的,就是1009的長度,所以如果常量池中的字符串過多就會導致效率下降很快。在jdk7中,StringTable的長度可以通過一個參數指定:

-XX:StringTableSize=99991

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

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

相關文章

MinCED:注釋CRISPRs

GitHub - ctSkennerton/minced: Mining CRISPRs in Environmental Datasets 安裝 git clone http://github.com/ctSkennerton/minced cd minced make 使用 gunzip -k * cat *.fa > all_MAG_contig.fasta /home/zhongpei/hard_disk_sda2/zhongpei/Software/minced/minced…

NeurIPS‘24 截稿日期逼近 加拿大溫哥華邀你共赴盛會

會議之眼 快訊 第38屆NeurIPS24(Conference and Workshop on Neural Information Processing Systems)即神經信息處理系統研討會將于 2024 年 12月9日-15日在加拿大溫哥華會議中心舉行! NeurIPS 每一年都是全球AI領域的一場盛宴,吸引著來自世界各地的頂…

暴雨信息:IT是新質生產力的賦能者

5月11日下午,2024全球徽商上海論壇在上海國際會議中心舉辦。暴雨信息孫輝在會上發表歡迎辭。孫輝在致辭和會后接受采訪時表示,發展新質生產力要以“智”提質,發揮人工智能作為培育新質生產力的引擎作用,通過推廣混合式人工智能&am…

【小白誤闖】Activiti 框架你不得不知道的一些事

Activiti 是一個輕量級的、以Java為中心的開源工作流和業務流程管理(BPM)平臺。它允許用戶在業務應用程序中定義、執行和監控業務流程。以下是Activiti的核心組件: 8個核心組件概述 Activiti Engine:這是Activiti最核心的部分&am…

Java 面試問題及答案

Java 面試問題及答案 問題 1: 什么是Java虛擬機(JVM)?請簡述其主要組成部分及其作用。 回答: Java虛擬機(JVM)是一個可以執行Java字節碼的虛擬計算機。它是Java平臺的核心組成部分,使得Java能夠實現其核心特性之一&a…

Elasticsearch映射定義

文章目錄 認識映射元字段數據類型1.基本數據類型2.復雜數據類型專用數據類型多字段類型 認識映射 映射類似于關系型數據庫中的Schema(模式)。Schema在關系型數據庫中是指庫表包含的字段及字段存儲類型等基礎信息。 映射定義由兩部分組成:元…

一些python包缺失帶來的報錯及解決辦法

描述 一些python包缺失帶來的報錯及解決辦法 安裝 ModuleNotFoundError: No module named cv2 pip install opencv-pythonModuleNotFoundError: No module named torch 我的CSDN博客ModuleNotFoundError: No module named colorama pip install coloramaModuleNotFoundError…

5.10.8 Transformer in Transformer

Transformer iN Transformer (TNT)。具體來說,我們將局部補丁(例如,1616)視為“視覺句子”,并將它們進一步劃分為更小的補丁(例如,44)作為“視覺單詞”。每個單詞的注意力將與給定視…

信號和槽基本概念

🐌博主主頁:🐌?倔強的大蝸牛🐌? 📚專欄分類:QT??感謝大家點贊👍收藏?評論?? 目錄 一、概述 二、信號的本質 三、槽的本質 一、概述 在 Qt 中,用戶和控件的每次交互過程稱…

Bootloader+升級方案

隨著設備的功能越來越強大,系統也越來越復雜,產品升級也成為了開發過程不可或缺的一道程序。在工程應用中,如何在不更改硬件的前提下通過軟件的方式實現產品升級。通過Bootloader來實現固件的升級是一種極好的方式,Bootloader是單…

I2CKD : INTRA- AND INTER-CLASS KNOWLEDGE DISTILLATION FOR SEMANTIC SEGMENTATION

摘要 本文提出了一種新的針對圖像語義分割的知識蒸餾方法,稱為類內和類間知識蒸餾(I2CKD)。該方法的重點是在教師(繁瑣模型)和學生(緊湊模型)的中間層之間捕獲和傳遞知識。對于知識提取&#x…

12個乒乓球,有一個次品,不知輕重,用一臺無砝碼天平稱三次,找出次品,告知輕重?

前言 B站上看到個視頻:為什么有人不認可清北的學生大多是智商高的? 然后試了下,發現我真菜 自己的思路(失敗) 三次稱重要獲取到12個乒乓球中那個是次品,我想著將12個小球編號,分為四組,每組…

yo!這里是socket網絡編程相關介紹

目錄 前言 基本概念 源ip&&目的ip 源端口號&&目的端口號 udp&&tcp初識 socket編程 網絡字節序 socket常見接口 socket bind listen accept connect 地址轉換函數 字符串轉in_addr in_addr轉字符串 套接字讀寫函數 recvfrom&&a…

Java入門基礎學習筆記2——JDK的選擇下載安裝

搭建Java的開發環境: Java的產品叫JDK(Java Development Kit: Java開發者工具包),必須安裝JDK才能使用Java。 JDK的發展史: LTS:Long-term Support:長期支持版。指的Java會對這些版…

pycharm報錯Process finished with exit code -1073740791 (0xC0000409)

pycharm報錯Process finished with exit code -1073740791 (0xC0000409) 各種垃圾文章(包括chatgpt產生的垃圾文章),沒有給出具體的解決辦法。 解決辦法就是把具體報錯信息顯示出來,然后再去查。 勾選 然后再運行就能把錯誤顯示…

MetaRTC-play拉流客戶端代碼分析

渲染使用opengl,音頻播放使用alsa。 當點擊播放按鈕后,以此調用的類如下,開始建立rtc連接,AV解碼,音頻渲染,視頻渲染。 如果想去除QT,改為cmake工程管理,去掉渲染部分即可。 下方是…

VUE+PrintJS打印-邊距設置問題(提供解決方案)

VUE打印我們一般用printJS,雖然它也提供了邊距設置,但不管怎么調,感覺都不對,也換其他組件試過,沒啥區別,并不能解決問題。 今天又發來個需求,要求設置打印頁面的上、下、左、右邊距&#xff0…

Linux---vim編輯器(續寫)

5. vim正常模式命令集 插入模式 按「i」切換進入插入模式「insert mode」, 按“i”進入插入模式后是從光標當前位置開始輸入文件; 按「a」進入插入模式后,是從目前光標所在位置的下一個位置開始輸入文字; 按「o」進入插入模式…

從頭開始學Spring—01Spring介紹和IOC容器思想

目錄 1.Spring介紹 1.1Spring概述 1.2特性 1.3五大功能模塊 2.IOC容器 2.1IOC思想 ①獲取資源的傳統方式 ②反轉控制方式獲取資源 ③DI 2.2IOC容器在Spring中的實現 ①BeanFactory ②ApplicationContext ③ApplicationContext的主要實現類 1.Spring介紹 1.1Sprin…

Linux系統一步一腳印式學習

Linux操作系統具有許多特點和優勢。首先,它是開放源代碼的,也就意味著任何人都可以對源代碼進行查看和修改。其次,可以同時支持多個用戶且可以同時執行多個任務,此外,Linux操作系統也非常穩定和安全。相對于其他操作系…