欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

JVM分配和回收堆外內(nèi)存的方式與注意點(diǎn)

 更新時(shí)間:2022年07月04日 08:24:39   作者:陳湯姆  
JVM啟動時(shí)分配的內(nèi)存稱為堆內(nèi)存,與之相對的,在代碼中還可以使用堆外內(nèi)存,比如Netty,廣泛使用了堆外內(nèi)存,下面這篇文章主要給大家介紹了關(guān)于JVM分配和回收堆外內(nèi)存的方式與注意點(diǎn),需要的朋友可以參考下

JVM內(nèi)存模型

在JVM中內(nèi)存被分成兩大塊,分別是堆內(nèi)存和堆外內(nèi)存,堆內(nèi)存就是JVM使用的內(nèi)存,而堆外內(nèi)存就是非JVM使用的內(nèi)存,一般是分配給機(jī)器使用的內(nèi)存。

那么整個(gè)內(nèi)存模型如下:

因此在JVM中正常只能分配之際獨(dú)有的內(nèi)存即堆內(nèi)存,而我們知道JVM并不建議開發(fā)者直接操作堆外內(nèi)存的,因此容易造成內(nèi)存泄漏,并且難以排查,但是在JVM中是可以操作堆外內(nèi)存的并且也可以回收堆外內(nèi)存,但是是一種不建議的方式。

如何分配堆外內(nèi)存

那么在堆內(nèi)存中如何分配堆外內(nèi)存呢?

在Java中存在兩種方式分配堆外內(nèi)存,分別是ByteBuffer#allocateDirect和Unsafe#allocateMemory。

可能第一個(gè)會經(jīng)常使用到,這是Java NIO提供的一個(gè)分配內(nèi)存的類,在做網(wǎng)絡(luò)開發(fā)時(shí)會經(jīng)常使用該方式進(jìn)行分配內(nèi)存,而第二種方式是Unsafe的方式,我們知道Unsafe是一種不安全的類,該類是提供給開發(fā)者操作最底層數(shù)據(jù)的類,類似C或者C++直接操作內(nèi)存的方式,因此該類并不建議使用,如果使用該類分配內(nèi)存但是沒有及時(shí)回收容易造成內(nèi)存泄漏。

第一種方式:ByteBuffer#allocateDirect

該類分配內(nèi)存的實(shí)現(xiàn)方式如下:

//分配10M的內(nèi)存
ByteBuffer byteBuffer = ByteBuffer.allocateDirect(10 * 1024 * 1024);

通過該方式分配堆外內(nèi)存其實(shí)最底層還是使用的是Unsafe#allocateMemory進(jìn)行分配內(nèi)存,ByteBuffer只是對Unsafe做了一層封裝。

第二種方式:Unsafe#allocateMemory

public class Test {
    private static Unsafe unsafe = null;
    public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException {
        //分配10M的內(nèi)存
        Field getUnsafe = Unsafe.class.getDeclaredField("theUnsafe");
        getUnsafe.setAccessible(true);
        unsafe = (Unsafe)getUnsafe.get(null);
        //分配完內(nèi)存返回內(nèi)存的地址
        long address = unsafe.allocateMemory(10 * 1024 * 1024);
    }
}

該方式中Unsafe類并不能直接被使用,但是可以通過反射的方式使用該類,該類分配內(nèi)存后需要手動回收,不然被分配的內(nèi)存不會被釋放。

如何回收堆外內(nèi)存

說完了如何分配內(nèi)存,那么繼續(xù)了解如何回收堆外內(nèi)存。

第一種方式:Unsafe#freeMemory

分配堆外內(nèi)存的兩種方式中,第二種Unsafe的方式其實(shí)提供了一個(gè)釋放堆外內(nèi)存的實(shí)現(xiàn),實(shí)現(xiàn)如下:

public class Test {
    private static Unsafe unsafe = null;
    public static void main(String[] args) throws NoSuchFieldException, IllegalAccessException {
        //分配10M的內(nèi)存
        Field getUnsafe = Unsafe.class.getDeclaredField("theUnsafe");
        getUnsafe.setAccessible(true);
        unsafe = (Unsafe)getUnsafe.get(null);
        //分配完內(nèi)存返回內(nèi)存的地址
        long address = unsafe.allocateMemory(10 * 1024 * 1024);
        //回收分配的堆外內(nèi)存
        unsafe.freeMemory(address);
    }
}

在Unsafe中提供了freeMemory的實(shí)現(xiàn)進(jìn)行回收堆外內(nèi)存,但是前提是需要知道被分配的堆外內(nèi)存地址才可以實(shí)現(xiàn)對應(yīng)的內(nèi)存回收。

這種回收堆外內(nèi)存的方式其實(shí)是開發(fā)者自己手動回收,并不是由JVM引起的內(nèi)存回收,那么JVM如何回收堆外內(nèi)存呢?

第二種方式:JVM回收堆外內(nèi)存

通過ByteBuffer#allocateDirect分配的堆外內(nèi)存在JVM中其實(shí)也是存在一定的內(nèi)存占用的,具體關(guān)聯(lián)關(guān)系如下:

當(dāng)通過ByteBuffer#allocateDirect分配堆外內(nèi)存后,會將堆外內(nèi)存的地址、大小等信息通過DirectByteBuffer進(jìn)行關(guān)聯(lián),那么堆內(nèi)存中就可以關(guān)聯(lián)到堆外內(nèi)存。

那么Cleaner又是什么東西呢?

了解Cleaner需要知道JVM中四種引用方式:強(qiáng)引用、弱引用、軟引用、虛引用,Cleaner就是虛引用的實(shí)現(xiàn),上圖中的ReferenceQueue就是一個(gè)引用隊(duì)列,將需要回收的Cleaner放入到該隊(duì)列中,實(shí)現(xiàn)邏輯如下:

  • JVM執(zhí)行Full GC時(shí)會將DirectByteBuffer進(jìn)行回收,回收之后Clearner就不存在引用關(guān)系
  • 再下一次發(fā)生GC時(shí)會將Cleaner對象放入ReferenceQueue中,同時(shí)將Cleaner從鏈表中移除
  • 最后調(diào)用unsafe#freeMemory清除堆外內(nèi)存

那么可能會存在疑問,為什么DirectByteBuffer 會被回收呢?

首先DirectByteBuffer 是存在堆內(nèi)存中的對象,那么既然存在堆內(nèi)存中就會發(fā)生GC晉級,即晉升到老年代中,在老年代中就會發(fā)生Full GC或者Old GC。

注意點(diǎn)

注意點(diǎn)1:

在實(shí)際使用DirectByteBuffer 時(shí)要避免把內(nèi)存使用完,但是在實(shí)際操作中我們可能不知道堆外內(nèi)存還剩余多少,因此我們可以在JVM中通過參數(shù)控制,通過JVM參數(shù) -XX:MaxDirectMemorySize 指定堆外內(nèi)存的上限大小,當(dāng)超過指定的內(nèi)存上限大小時(shí),會主動觸發(fā)一次Full GC進(jìn)行回收內(nèi)存。

注意點(diǎn)2:

通過DirectByteBuffer 分配內(nèi)存時(shí),可能會出現(xiàn)分配內(nèi)存不夠的情況,因此JVM如果發(fā)現(xiàn)堆外內(nèi)存分配不足時(shí),也會主動發(fā)起一次GC,只不過這次GC是通過System.gc() 實(shí)現(xiàn)的強(qiáng)制GC,但是在實(shí)際生產(chǎn)環(huán)境中我們都是通過JVM參數(shù) -XX:+DisableExplicitGC,禁止使用System.gc()的,因此在實(shí)際使用過程中一定要注意分配內(nèi)存的情況,避免出現(xiàn)內(nèi)存泄漏。

引用

  • Netty 核心原理剖析與 RPC 實(shí)踐

總結(jié)

到此這篇關(guān)于JVM分配和回收堆外內(nèi)存的方式與注意點(diǎn)的文章就介紹到這了,更多相關(guān)JVM分配回收堆外內(nèi)存內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • Maven中pom.xml文件報(bào)錯(cuò)的原因解決

    Maven中pom.xml文件報(bào)錯(cuò)的原因解決

    創(chuàng)建Maven項(xiàng)目的時(shí)候,如果你選擇的Packaging為war,那么就會報(bào)錯(cuò),本文主要介紹了Maven中pom.xml文件報(bào)錯(cuò)的原因解決,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-07-07
  • SpringBoot中使用Ehcache的詳細(xì)教程

    SpringBoot中使用Ehcache的詳細(xì)教程

    EhCache 是一個(gè)純 Java 的進(jìn)程內(nèi)緩存框架,具有快速、精干等特點(diǎn),是 Hibernate 中默認(rèn)的 CacheProvider。這篇文章主要介紹了SpringBoot中使用Ehcache的相關(guān)知識,需要的朋友可以參考下
    2020-08-08
  • 實(shí)例詳解Java8函數(shù)式接口

    實(shí)例詳解Java8函數(shù)式接口

    本文給大家分析了Java8默認(rèn)方法和函數(shù)式接口實(shí)例其它創(chuàng)建方式,需要的朋友跟著學(xué)習(xí)下吧。
    2017-11-11
  • java獲取當(dāng)前時(shí)間戳的方法

    java獲取當(dāng)前時(shí)間戳的方法

    本文主要介紹了java獲取當(dāng)前時(shí)間戳的方法,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2023-06-06
  • Java 中Map 的用法詳解

    Java 中Map 的用法詳解

    本文主要介紹java 中的Map 接口, 這里對Map 接口下的幾個(gè)類做了詳細(xì)介紹,希望對學(xué)習(xí)java 編程的小伙伴有所幫助
    2016-07-07
  • 聊一聊SpringBoot服務(wù)監(jiān)控機(jī)制

    聊一聊SpringBoot服務(wù)監(jiān)控機(jī)制

    這篇文章主要介紹了聊一聊SpringBoot服務(wù)監(jiān)控機(jī)制,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-04-04
  • JDK反序列化時(shí)修改類的全限定性名解析

    JDK反序列化時(shí)修改類的全限定性名解析

    這篇文章主要介紹了JDK反序列化時(shí)修改類的全限定性名解析,具有一定借鑒價(jià)值,需要的朋友可以參考下。
    2017-12-12
  • java文字轉(zhuǎn)語音的實(shí)現(xiàn)示例

    java文字轉(zhuǎn)語音的實(shí)現(xiàn)示例

    在Java中,我們可以使用第三方庫來實(shí)現(xiàn)文字轉(zhuǎn)語音的功能,本文主要介紹了java文字轉(zhuǎn)語音的實(shí)現(xiàn)示例,選擇jacob技術(shù)實(shí)現(xiàn),具有一定的參考價(jià)值,感興趣的可以了解一下
    2024-03-03
  • 分享幾個(gè)Java工作中實(shí)用的代碼優(yōu)化技巧

    分享幾個(gè)Java工作中實(shí)用的代碼優(yōu)化技巧

    這篇文章主要給大家分享幾個(gè)Java工作中實(shí)用代碼優(yōu)化技巧,文章基于Java的相關(guān)資料展開對其優(yōu)化技巧的分享,需要的小伙伴可以參考一下
    2022-04-04
  • Java終止循環(huán)體的具體實(shí)現(xiàn)

    Java終止循環(huán)體的具體實(shí)現(xiàn)

    這篇文章主要介紹了Java終止循環(huán)體的具體實(shí)現(xiàn),需要的朋友可以參考下
    2014-02-02

最新評論