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

去京東面試問我JVM堆外內存是什么,我直接麻了,趕緊復習

開發 前端
這個 JVM 里的堆內存是有劃分的,一塊區域是年輕代,一塊區域是老年代,像這種緩存數據,因為是長期存在堆內存里的,所以通常會在年輕代里待一段時間,然后因為沒法垃圾回收,給放到老年代里去。

?今天給大家聊一個很有意思的知識,就是 off-heap 堆外內存,平時出去面試,或者研究一些技術的時候,經常可能會遇到 off-heap 堆外內存這個東西,但是很多人可能還不知道 off-heap 堆外內存到底是什么,所以今天就給大家來深入的分析一下。

on-heap 堆內內存是什么?

要說這個 off-heap 堆外內存,就得先說 on-heap 也就是堆內內存,這個 on-heap 堆內內存相信很多人應該都是熟悉的。

那就是咱們平時寫好的 Java 系統其實運行起來就是一個 JVM 進程,這個 JVM 進程是有一塊內存空間專門給他用的,這塊內存空間就是堆內內存。

大概如下圖所示:

JVM 堆內存是如何去劃分的?

那么這里通常會產生什么問題呢?一般來說沒什么大問題,但是如果是遇到要把大量數據緩存在 JVM 堆內存里的時候,就可能會有問題了。

所謂的數據緩存,意思就是說,把很多數據存放在堆內存里,這些數據是要一直用的,所以一般來說不能把他回收掉,所以會導致可能很多數據一直停留在 JVM 的堆內存里。

如下圖:

那么下一個問題來了,這個 JVM 里的堆內存是有劃分的,一塊區域是年輕代,一塊區域是老年代,像這種緩存數據,因為是長期存在堆內存里的,所以通常會在年輕代里待一段時間,然后因為沒法垃圾回收,給放到老年代里去。

此時如下圖:

JVM 堆內存滿了后會怎么樣?

但是這個老年代里如果放了太多緩存數據以后,就可能會導致他剩余的可用空間就會比較少了,此時可能會導致老年代經常會放一點別的數據就塞滿了,一旦塞滿了就會觸發 JVM 的 Full GC,有一個垃圾回收線程會去回收老年代里的數據。

此時如下圖:

可是此時一般來說能回收的也就是除了緩存數據之外的一些空間,哪怕你回收了,但是緩存數據是要一直存在的,所以沒法回收掉。

此時會導致每次你回收了一部分剩余空間之后,然后還是剩余了很多緩存數據,此時對于緩存數據來說會一直占據老年代的很大空間。

那么此時必然導致一個現象,那就是老年代會頻繁的寫一點數據就滿了,寫一點數據就滿了,然后一會兒就得觸發一下 Full GC。

每次 Full GC 都會導致 JVM 停止運行,沒法處理外部請求,此時對外部來說,就會感覺你的系統性能經常抖動,一會卡一下,一會兒卡一下。

所以往往來說,把很多數據緩存在 JVM 內部,是很可能導致上述現象,就是老年代頻繁塞滿、頻繁觸發 Full GC、頻繁導致系統停頓沒法處理請求。

如下圖:

基于堆外內存解決系統 GC 卡頓問題

所以針對這種情況,往往我們的優化手段,就是會把要緩存的數據,從 JVM 堆內存里轉移到 offheap 堆外內存里去,那所以問題來了,啥叫做堆外內存呢?

就是顧名思義,不歸 JVM 管的內存區域,OS 操作系統負責管理的一部分內存,叫做堆外內存。

所以我們其實可以選擇把很多數據直接寫入到堆外內存里去,這樣的話,就不會占用 JVM 堆中的老年代空間了,也就不會導致老年代頻繁塞滿,頻繁觸發 Full GC,導致系統性能頻繁抖動了。

如下圖:

那既然這個堆外內存這么好,問題來了,他有什么缺點呢?

當然有了,因為如果你用的是 JVM 堆內的內存,你寫入了很多數據以后,如果內存滿了,此時 JVM 會自動進行垃圾回收,幫你釋放掉一些內存空間,他是全自動的。

但是如果你用的是堆外內存,那可沒有 JVM 來幫你管理了,此時你必須自己管理那塊內存空間。

也就是說,你寫入了數據以后,到了需要的時候,你得自己注意把部分內存進行釋放,所以這就導致了堆外內存雖然不會導致你的 JVM 頻繁 GC,但是他可能會導致你的代碼管理難度變高。

如下圖:

那么這個堆外內存一般來說我們用 Java 代碼是如何申請的呢?

看下面的代碼,一般類似 Netty、RocketMQ 等中間件因為就是要管理大量的內存數據,所以都會選擇申請一塊堆外內存,把數據放在里面,自己進行精細化的管理。

// 定義好要申請的堆外內存的大小,這里是1GB
int memorySize = 1024 * 1024 * 1024;
// 用Java里的ByteBuffer.allocateDirect方法就可以申請一塊堆外內存
ByteBuffer byteBuffer = ByteBuffer.allocateDirect(memorySize);
// 把數據寫入到堆外內存里去
byte[] bytes = "hello world".getBytes();
byteBuffer.put(bytes);
// 從堆外內存里讀取數據
byteBuffer.flip();
byte[] readBytes = new byte[bytes.length];
byteBuffer.get(readBytes, 0, bytes.length);

那大家通過這塊代碼看到了我們如何申請堆外內存,以及如何往堆外內存里寫入數據和如何讀取數據之后,現在思考一下,堆外內存我們應該如何進行釋放呢?

是這樣的,這個堆外內存其實是被 JVM 堆內的一個 ByteBuffer 對象來引用的,所以如果要是 JVM 堆內的 ByteBuffer 對象被回收了,那他關聯的堆外內存就會被釋放了。

如下圖:

好了,今天的知識點就分享到這里了,相信大家看完之后應該對堆外內存這個概念有了一個較為清晰的認識了。?

責任編輯:武曉燕 來源: 今日頭條
相關推薦

2024-07-01 00:00:02

2024-05-21 09:08:57

JVM調優面試

2017-01-11 14:02:32

JVM源碼內存

2022-07-03 20:31:59

JVMJava虛擬機

2019-04-28 11:48:54

Python面試工程師

2020-03-27 16:27:03

Redis數據庫

2023-10-04 19:43:38

2024-05-24 10:36:27

2023-12-04 10:36:46

SessionCookie

2021-09-09 18:12:22

內存分段式網絡

2020-08-27 21:36:50

JVM內存泄漏

2021-06-03 08:55:54

分布式事務ACID

2021-12-02 08:19:06

MVCC面試數據庫

2018-09-28 05:25:53

TopK算法代碼

2022-04-10 18:10:24

CURD鏈表

2021-10-25 08:49:32

索引數據庫MySQL

2023-08-26 19:23:40

Javastatic關鍵字

2011-05-24 14:15:53

測試

2018-11-01 13:49:23

桶排序排序面試

2018-10-28 22:37:00

計數排序排序面試
點贊
收藏

51CTO技術棧公眾號

主站蜘蛛池模板: 五月激情婷婷在线 | 国产电影一区二区在线观看 | 一级免费毛片 | 一区二区日韩 | 国产精品毛片一区二区在线看 | 97免费在线观看视频 | 天天射网站 | 亚洲欧美aⅴ | 国产高潮好爽受不了了夜色 | 久久日本 | 国产日产精品一区二区三区四区 | 综合久久综合久久 | 日日操夜夜操天天操 | 欧美日韩国产高清视频 | 欧美一级二级三级视频 | 亚洲综合色 | 在线一区视频 | 亚洲精品一区二区网址 | 日韩欧美精品一区 | 成人高清在线 | 一级黄色毛片 | 国产欧美精品一区二区色综合朱莉 | 日韩中文字幕网 | 北条麻妃一区二区三区在线视频 | 91视视频在线观看入口直接观看 | 黄色播放 | 久久亚洲精品国产精品紫薇 | 日本不卡一区二区三区在线观看 | 成年人在线观看 | 欧美成人手机视频 | 一级片在线观看 | 亚洲精品99| 午夜影院在线视频 | 欧美性受xxxx | 精品久久久久久久久久 | 动漫www.被爆羞羞av44 | 国产一区二 | 欧美一级片中文字幕 | 国产精品不卡 | 天天插天天操 | 在线免费观看日本 |