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

我接手前同事寫的爛Java代碼,不小心搞出了一個(gè)內(nèi)存泄露事故

開發(fā) 前端
當(dāng)我們平時(shí)在代碼中寫下一行 String 類型的代碼時(shí),大家知道這個(gè) String 字符串在內(nèi)存里是如何存儲(chǔ)的嗎?

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

String 字符串在內(nèi)存里是如何存儲(chǔ)的?

首先呢,當(dāng)我們平時(shí)在代碼中寫下一行 String 類型的代碼時(shí),大家知道這個(gè) String 字符串在內(nèi)存里是如何存儲(chǔ)的嗎?

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

如下圖:

接著呢,對(duì)于 Java 中的字符串來說,有一個(gè)常量池的概念,意思就是說,對(duì)于相同的字符串內(nèi)容,他往往會(huì)在內(nèi)存里用同一個(gè)數(shù)組來表示,而不會(huì)對(duì)相同的字符串內(nèi)容創(chuàng)建出不同的數(shù)組來存放。

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

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

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

如下圖所示:

所以說,正是因?yàn)橄嗤淖址且玫耐粋€(gè)底層的數(shù)組,所以如果用類似于 System.out.println(username == nickname) 這種判斷代碼的話,會(huì)發(fā)現(xiàn) username == nickname 返回的是 true,因?yàn)樗麄儌z就是指向了底層同一個(gè)數(shù)組的。

另外再給大家普及一個(gè)字符串的知識(shí)點(diǎn),那就是如果我們用一個(gè)字符串創(chuàng)建一個(gè) String 對(duì)象的話,那他在內(nèi)存里一定是另外的一個(gè)對(duì)象了。

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

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

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

那不可能的,此時(shí)一定是 false,因?yàn)榇藭r(shí)在內(nèi)存里,username 是指向一個(gè)數(shù)組的,但是 nickname 是指向一個(gè) String 對(duì)象的,只不過這個(gè) String 對(duì)象里面是有一個(gè)"zhangsan"字符串而已。

如下圖:

但是這個(gè)時(shí)候又給大家再次介紹一個(gè)知識(shí)點(diǎn)了,那就是這個(gè) String 對(duì)象內(nèi)部的"zhangsan"字符串,是怎么存儲(chǔ)的呢?

其實(shí)啊,這個(gè) String 對(duì)象內(nèi)部的"zhangsan"字符串還是引用了之前的那個(gè)數(shù)組的,如下圖所示:

String.intern() 方法

所以說,如果此時(shí)你用 String.intern() 方法,就會(huì)發(fā)現(xiàn)你可以拿到 String 對(duì)象里的"zhangsan"字符串,此時(shí)再用這個(gè)字符串做比較,還是返回的是 true。

大家看下面代碼就懂了:

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

String 字符串是如何引發(fā)內(nèi)存泄漏呢?

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

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

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

如下圖所示:

可是在這種運(yùn)作模式下就有一個(gè)問題了,就是你每次 substring 都會(huì)把原數(shù)組拷貝一份,可是對(duì)于你的子字符串來說僅僅是需要里面的一部分而已,而你缺把原字符串每次都拷貝一份,導(dǎo)致了子字符串中不需要的那部分拷貝內(nèi)容都是浪費(fèi)掉的。

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

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

就是典型的內(nèi)存泄漏了,也就是說,你要是大量的進(jìn)行 substring 一類的操作,就可能會(huì)大量的拷貝字符串?dāng)?shù)組,然后很多拷貝后的字符串?dāng)?shù)組里,很多內(nèi)容都是不需要用的,結(jié)果還占據(jù)了很多內(nèi)存空間,這就叫做內(nèi)存泄漏。

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

所以后來在 Java 7 版本開始就對(duì) String.substring() 進(jìn)行了源碼重構(gòu),開始改造了這部分的實(shí)現(xiàn),每次你執(zhí)行 String.substring,他是把原字符串?dāng)?shù)組中你需要的那部分拷貝過來就可以了,就避免了每次都重復(fù)的拷貝原字符串?dāng)?shù)組。

如下圖:

總結(jié)

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

當(dāng)然現(xiàn)在一般都是用 Java 8 以上的版本,尤其較多的是用 Java 9、Java 10 甚至 Java 11 這幾個(gè)新版本了。

但是不排除有一些公司的非常老舊的系統(tǒng)在維護(hù)的時(shí)候,用的還是曾經(jīng)很風(fēng)靡的 Java 6 這個(gè)版本,大家在對(duì)這類老系統(tǒng)維護(hù)的時(shí)候,一定要謹(jǐn)慎注意 substring 內(nèi)存泄漏問題。

責(zé)任編輯:姜華 來源: 今日頭條
相關(guān)推薦

2021-05-11 16:20:02

網(wǎng)站HTTPHTTPS

2020-10-26 08:56:32

技術(shù)總監(jiān)程序員

2020-10-28 15:07:01

Arthas

2021-10-07 16:45:06

MySQL數(shù)據(jù)庫

2022-10-25 17:53:09

Java線程池

2021-07-28 05:01:29

Lombok前端測(cè)試

2021-01-05 22:49:37

Python編程語言Java

2020-05-19 08:30:33

kill -9命令Linux

2015-05-05 16:33:38

Easyrecover

2021-07-06 07:21:17

橋接模式組合

2019-07-29 14:38:35

服務(wù)器開發(fā)工具

2023-03-10 08:27:07

for循環(huán)項(xiàng)目線性結(jié)構(gòu)

2024-12-11 10:11:02

2020-09-29 07:44:20

跨域前后端分離插件

2021-04-30 08:21:22

Linux管道設(shè)計(jì)

2015-10-14 10:29:43

容器混搭Redis線上故障

2020-02-03 09:10:23

數(shù)據(jù)庫刪庫刪庫跑路

2022-03-23 08:01:04

Python語言代碼

2023-01-16 07:35:40

代碼編碼重構(gòu)

2018-01-18 22:26:30

點(diǎn)贊
收藏

51CTO技術(shù)棧公眾號(hào)

主站蜘蛛池模板: 99精品免费久久久久久久久日本 | 欧美久久一区 | 中文字幕第一页在线 | 国产精品久久久久久久久久免费看 | 亚欧精品一区 | 国产精品污www一区二区三区 | 黄色毛片网站在线观看 | 国产片淫级awww | 色综合激情 | 国产成人精品免费视频大全最热 | 伊人影院在线观看 | 欲色av| 91在线观看网址 | 国产专区免费 | 天天干成人网 | 先锋资源亚洲 | 国产成人精品久久二区二区 | 日韩中文字幕在线视频 | 欧美一级片在线观看 | 日本激情视频在线播放 | 日韩视频三区 | 成人午夜影院 | 欧美一区二区三区在线观看 | 中文字幕第一页在线 | 国产精品亚洲第一 | 国产精品免费在线 | h片在线免费看 | 国产精品一区二区av | 国产午夜三级一区二区三 | 久久在线视频 | 日韩精品专区在线影院重磅 | 久久小视频 | 欧美日韩中 | 亚洲综合大片69999 | www.天天操| 中文日本在线 | 欧美性大战久久久久久久蜜臀 | 99re在线免费视频 | zzzwww在线看片免费 | 久久成人国产精品 | www.亚洲视频.com|