成人免费xxxxx在线视频软件_久久精品久久久_亚洲国产精品久久久_天天色天天色_亚洲人成一区_欧美一级欧美三级在线观看

小心!用String寫代碼可能會內存泄漏!

開發 后端
今天給大家聊聊咱們平時寫代碼的時候,最常見的 String 字符串代碼,他的一些底層原理,以及使用不當可能引發的內存泄漏的問題,相信對于大家平時日常開發寫代碼會有一定的幫助。

目錄

  • String 字符串在內存里是如何存儲的?
  • String.intern() 方法
  • String 字符串是如何引發內存泄漏呢?
  • 總結

今天給大家聊聊咱們平時寫代碼的時候,最常見的 String 字符串代碼,他的一些底層原理,以及使用不當可能引發的內存泄漏的問題,相信對于大家平時日常開發寫代碼會有一定的幫助。

String 字符串在內存里是如何存儲的?

首先呢,當我們平時在代碼中寫下一行 String 類型的代碼時,大家知道這個 String 字符串在內存里是如何存儲的嗎?

比如這樣的一行代碼:String username = "zhangsan",這個"zhangsan"其實就是一串字符串,實際上他在底層是用一個數組來存放的,而且這個數組大小就嚴格等于這個字符串的長度,他是不可變的。

如下圖:

接著呢,對于 Java 中的字符串來說,有一個常量池的概念,意思就是說,對于相同的字符串內容,他往往會在內存里用同一個數組來表示,而不會對相同的字符串內容創建出不同的數組來存放。

比如說下面兩行代碼,大家看看:

String username = "zhangsan"; 
String nickname = "zhangsan";

上面的 username 和 nickname 他們兩個字符串指向的內容都是"zhangsan",實際上在底層都是用同一個數組來存放的。

如下圖所示:

所以說,正是因為相同的字符串是引用的同一個底層的數組,所以如果用類似于 System.out.println(username == nickname) 這種判斷代碼的話,會發現 username == nickname 返回的是 true,因為他們倆就是指向了底層同一個數組的。

另外再給大家普及一個字符串的知識點,那就是如果我們用一個字符串創建一個 String 對象的話,那他在內存里一定是另外的一個對象了。

如下代碼所示,大家看看:

String username = "zhangsan"; 
String nickname = new String("zhangsan");
System.out.println(username == nickname);

大家看上面代碼,此時 username 和 nickname 比較還是返回 true 嗎?

那不可能的,此時一定是 false,因為此時在內存里,username 是指向一個數組的,但是 nickname 是指向一個 String 對象的,只不過這個 String 對象里面是有一個"zhangsan"字符串而已。

如下圖:

但是這個時候又給大家再次介紹一個知識點了,那就是這個 String 對象內部的"zhangsan"字符串,是怎么存儲的呢?

其實啊,這個 String 對象內部的"zhangsan"字符串還是引用了之前的那個數組的,如下圖所示:

String.intern() 方法

所以說,如果此時你用 String.intern() 方法,就會發現你可以拿到 String 對象里的"zhangsan"字符串,此時再用這個字符串做比較,還是返回的是 true。

大家看下面代碼就懂了:

String username = "zhangsan"; 
String nickname = new String("zhangsan");
System.out.println(username == nickname.intern()); // 返回的是true

String 字符串是如何引發內存泄漏呢?

好,那么大家都理解了 Java 里字符串的基本原理后,我們就可以來給大家講講平時我們用字符串 String 寫代碼,一旦要是不注意,是如何引發內存泄漏問題的。

這個問題主要是出現在 Java 6 以及之前的版本里,在這個較為舊的 Java 版本中,String.substring() 這種字符串截取動作,是會導致內存泄漏的,什么意思呢,我們來看看。

在 Java 6 以前的版本中,當你調用 String.substring() 進行字符串截取的時候,他在底層的運作模式是這樣的,他會把你的原字符串的數組直接拷貝一份過來,然后用一個 offset 指針和 count 標記,來表名截取后的字符串你是需要哪些。

如下圖所示:

可是在這種運作模式下就有一個問題了,就是你每次 substring 都會把原數組拷貝一份,可是對于你的子字符串來說僅僅是需要里面的一部分而已,而你缺把原字符串每次都拷貝一份,導致了子字符串中不需要的那部分拷貝內容都是浪費掉的。

如下圖紅圈部分都是子字符串不需要的:

所以此時子字符串不需要的紅圈部分處的內容還依然占據了內存,這屬于什么問題呢?

就是典型的內存泄漏了,也就是說,你要是大量的進行 substring 一類的操作,就可能會大量的拷貝字符串數組,然后很多拷貝后的字符串數組里,很多內容都是不需要用的,結果還占據了很多內存空間,這就叫做內存泄漏。

內存泄漏指的就是你很多內存空間被占用了,結果你又不用他,別人也沒法用,就是典型的占著茅坑不拉屎的行為。

所以后來在 Java 7 版本開始就對 String.substring() 進行了源碼重構,開始改造了這部分的實現,每次你執行 String.substring,他是把原字符串數組中你需要的那部分拷貝過來就可以了,就避免了每次都重復的拷貝原字符串數組。

如下圖:

總結

在這種 Java 7 以及往后的新版本中,就徹底的解決了 substring 導致的內存泄漏問題了,因此大家平時在用字符串做開發的過程中,也一定要小心謹慎,避免誤用老版本的 Java 觸發這種內存泄漏隱患。

當然現在一般都是用 Java 8 以上的版本,尤其較多的是用 Java 9、Java 10 甚至 Java 11 這幾個新版本了。

但是不排除有一些公司的非常老舊的系統在維護的時候,用的還是曾經很風靡的 Java 6 這個版本,大家在對這類老系統維護的時候,一定要謹慎注意 substring 內存泄漏問題。

責任編輯:姜華 來源: 石杉的架構筆記
相關推薦

2016-12-27 18:43:33

iOS 10.2iPhone蘋果

2025-06-20 08:14:55

2020-07-06 07:48:16

MySQL細節SQL

2019-07-01 09:10:00

前端開發技術

2018-07-10 11:05:18

開發者技能命令

2017-03-23 16:03:01

2009-04-08 15:35:18

LinuxWindows文件系統

2012-12-10 10:19:01

Google NowChrome

2012-07-27 08:53:06

Windows 8微軟

2018-07-10 10:45:00

規范Commit項目

2016-07-05 14:09:02

AndroidJAVA內存

2018-01-17 22:29:14

2019-09-09 10:08:05

邊緣計算網絡物聯網

2022-06-01 08:00:58

KubernetesCPULinux

2021-02-22 10:01:16

人工智能黑客網絡安全

2023-04-24 14:26:32

2009-04-09 17:15:37

LinuxWindows文件系統

2022-02-18 10:17:30

5GWi-Fi應用案例

2016-10-31 20:56:57

Javascript閉包內存泄漏

2022-05-09 14:09:23

多線程線程安全
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 欧美中文字幕一区二区三区亚洲 | 天天曰夜夜 | 宅男噜噜噜66一区二区 | 午夜一区| 81精品国产乱码久久久久久 | 日本精品视频一区二区三区四区 | 国产一区 | 古装三级在线播放 | 久久精品亚洲欧美日韩精品中文字幕 | 精区3d动漫一品二品精区 | 亚洲欧美精品 | 日韩中文字幕在线视频观看 | 久久久91 | 99re视频在线观看 | 日韩欧美一区二区三区 | 成人av观看| 久久精品免费观看 | 欧美第一区| 91免费高清视频 | 成人在线中文字幕 | 夜夜久久 | 日韩中文字幕一区二区 | 成人永久免费视频 | 国产精品久久久久一区二区三区 | 午夜精品久久久久久久久久久久久 | 色吊丝2288sds中文字幕 | 国产精品视频一二三区 | av一二三区 | 国产亚洲精品久久久久动 | 中文字幕一区二区三区不卡 | 欧美不卡在线 | 91在线视频播放 | 成人精品一区二区三区 | 中文字幕国产精品视频 | 日韩久久久久久久 | 草久网 | 日干夜操 | 国产精品一区二区久久久久 | 亚洲精品一区二区另类图片 | 国产亚洲一区二区三区在线观看 | 黄色在线观看 |