日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > linux >内容正文

linux

Java 内存 关系_JVM和Linux之间的详细内存关系

發布時間:2024/7/23 linux 36 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Java 内存 关系_JVM和Linux之间的详细内存关系 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

JVM和Linux之間的詳細內存關系

在一些具有8g物理內存的服務器上,主要運行Java服務。系統內存分配如下:Java服務的JVM堆大小設置為6g,監視過程大約需要600m,Linux本身使用大約800m。

從表面上看,物理記憶應該足夠;但實際操作是會發生大量SWAP(表明物理內存不足),如下圖所示。由于同時發生SWAP和GC會導致JVM嚴重卡住,我們不得不問:內存在哪里?

JVM和Linux之間的詳細內存關系

JVM和Linux之間的詳細內存關系

要分析此問題,了解JVM與操作系統之間的內存關系非常重要。下一步是對Linux和JVM之間的內存關系進行一些分析。

首先,Linux和進程內存模型

JVM作為Linux系統上的進程運行。了解Linux和進程之間的內存關系是理解JVM和Linux內存之間關系的基礎。下圖顯示了硬件,系統和進程級別的內存之間的摘要關系。

JVM和Linux之間的詳細內存關系

從硬件角度來看,Linux系統的內存空間由兩部分組成:物理內存和SWAP(在磁盤上)。物理內存是Linux活動使用的主要內存區域;當物理內存不足時,Linux會將一些未使用的內存數據放入磁盤上的SWAP中,以釋放更多可用內存空間;使用位于SWAP中的數據時,必須先將其交換回內存。有關JVM運行時區域的詳細說明,我建議大家看一下。

從Linux系統來看,除了引導系統的BIN區域外,整個內存空間主要分為兩部分:內核內存(Kernel space),用戶內存(User space)。

內核內存是Linux本身使用的內存空間。它主要用于程序邏輯,例如程序調度,內存分配和連接硬件資源。

用戶內存提供給每個進程的主空間,Linux為每個進程提供相同的虛擬內存空間;這使得這些過程彼此獨立,并且不會相互干擾。實現方法是使用虛擬內存技術:為每個進程提供虛擬內存空間,僅在實際使用虛擬內存時分配物理內存。如下圖所示,對于32位的Linux系統,0到3G的虛擬內存空間分配通常用作用戶空間,3到4G的虛擬內存空間分配為內核空間; 64位系統的劃分是類似的。 。

JVM和Linux之間的詳細內存關系

從過程的角度來看,進程可以直接訪問的用戶存儲器(虛擬存儲空間)分為五個部分:代碼區,數據區,堆區,堆棧區和未使用區。

應用程序的機器代碼代碼存儲在代碼區域中。代碼在運行過程中無法修改,具有只讀和固定大小的特征。

數據區存儲應用程序中的全局數據,靜態數據和一些常量字符串等,其大小也是固定的。

堆是動態應用運行時程序的空間,屬于程序運行時直接應用和釋放的內存資源。

堆棧區域用于存儲傳入參數,臨時變量和返回地址等數據。

未使用區域是用于分配新存儲空間的備用區域。

第二,進程和JVM內存空間

JVM本質上是一個進程,因此它的內存空間(也稱為運行時數據區,注意JMM之間的差異)也具有該進程的一般特征。在Java中深入解釋JVM內存管理,這個參考。

但是,JVM不是一個普通的進程,它在內存空間中有許多新功能。主要有兩個原因:

1. JVM將屬于操作系統管理范圍的許多東西移植到JVM,以減少系統調用的次數;

2. Java NIO,目的是減少讀寫IO系統調用的開銷。將JVM進程與正常進程內存模型進行比較,如下所示。:

JVM和Linux之間的詳細內存關系

應該注意的是,該模型不是JVM內存使用的準確模型,而是從操作系統的角度關注JVM的內部細節(盡管很重要)。下面從兩個方面描述JVM進程的內存特征:用戶內存和內核內存。

用戶記憶

上圖突出顯示了JVM進程模型的代碼區和數據區是指JVM本身,而不是Java程序。正常的進程堆棧區域通常僅用作JVM中的線程堆棧。 JVM堆區域和正常進程之間的差異是最大的,詳情如下:

第一個是永久性的一代。永久生成本質上是Java程序的代碼和數據區域。 Java程序中的類被加載到整個區域的不同數據結構中,包括常量池,字段,方法數據,方法體,構造函數以及類中的專用方法,實例初始化和接口初始化。該區域是操作系統堆的一部分;對于Java程序,這是容納程序本身和靜態資源的空間,允許JVM解釋Java程序的執行。其次是新一代和老年。新一代和老一代是Java程序實際使用的堆空間,主要用于存儲對象的存儲;但管理方法與普通流程有本質區別。

當正常進程在運行時向內存對象分配空間時,例如,當C ++執行新操作時,它會觸發分配內存空間的系統調用,并且操作系統的線程根據對象的大小分配空間,回報;同時,當程序釋放對象時例如,當C ++執行刪除操作時,它還會觸發系統調用,以通知操作系統對象可以回收操作系統對象占用的空間。

JVM對內存的使用與一般過程不同。 JVM將一個完整的內存區域(特定的大小可以在JVM參數中調整)作為一堆Java程序(分為新一代和老一代)應用于操作系統;當Java程序申請內存空間時,例如執行新操作,JVM將在這里。段空間根據所需大小分配給Java程序,并且Java程序不負責在釋放對象空間時通知JVM。垃圾對象內存空間由JVM回收。

JVM內存管理方法的優點是顯而易見的,包括:首先,減少系統調用的數量,JVM在為Java程序分配內存空間時不需要操作系統干預,只需要向操作系統申請內存當Java堆大小更改時。或者通知回收,每次分配和回收內存空間時,正常程序需要系統調用才能參與;二,減少內存泄漏,正常程序沒有(或不及時)通知釋放操作系統內存空間是內存泄漏的重要原因之一。并且由JVM管理,可以避免程序員造成的內存泄漏。

最后,有一個未使用的區域,這是一個用于分配新內存空間的備用區域。對于正常進程,此區域可用于堆和堆棧空間請求和釋放。該區域用于每個堆內存分配,因此大小經常變化;對于JVM進程,使用堆大小和線程堆棧。這個區域雖然堆大小一般調整較少,所以尺寸相對穩定。操作系統動態調整此區域的大小,并且此區域通常不分配實際物理內存,只允許進程在此區域中應用堆或堆棧空間。

2.內核內存

應用程序通常不直接處理內核內存,內核內存由操作系統管理和使用;然而,由于Linux專注于性能和改進,新功能允許應用程序使用內核內存或映射到內核空間。 Java NIO就是在這種背景下誕生的,它充分利用了Linux系統的新特性,提高了Java程序的IO性能。JVM和Linux之間的詳細內存關系

上圖顯示了Java NIO在Linux系統中使用的內核內存的分布。 Nio緩沖區主要包括:nio在使用各種通道時使用的ByteBuffer,Java程序主動使用ByteBuffer.allocateDirector來申請分配的Buffer。

在PageCache中,nio使用的內存主要包括:FileChannel.map模式打開文件占用映射所需的Cache,FileChannel.transferTo和FileChannel.transferFrom(圖中未顯示)。

可以通過JMX監視NIO Buffer和映射的使用,如下圖所示。但是,FileChannel的實現是通過系統調用使用本機PageCache。該過程對Java是透明的,無法監視這部分內存的使用情況。

JVM和Linux之間的詳細內存關系

Linux和Java NIO為程序打開內核內存空間,主要是為了減少不必要的復制,以減少IO操作系統調用的開銷。例如,使用常規方法和NIO將數據從磁盤文件發送到網卡時,將比較數據流,如下圖所示:

JVM和Linux之間的詳細內存關系

在內核內存和用戶內存之間復制數據是浪費資源和時間。從上圖中,我們可以看到NIO方法減少了內核內存和用戶內存之間的數據副本兩次。這是Java NIO高性能的重要機制之一(另一種是異步非阻塞)。

從上面可以看出,內核內存對Java程序性能也非常重要。因此,在劃分系統內存使用時,必須為內核留出一些空閑空間。

三,案例分析

1.內存分配問題

通過以上分析,省略較小的區域,可以總結JVM占用的內存:

JVM內存≈Java永久代+ Java堆(新一代和老一代)+線程堆棧+ Java NIO

回到本文開頭提出的問題,原來的內存分配是:6g(java堆)+ 600m(監控)+ 800m(系統),剩下的600m內存未分配。

現在分析這個600m內存的分配:

Linux保留了大約200米,這是Linux正常運行的必要條件。

Java服務的線程數為160.JVM的默認線程堆棧大小為1m,因此使用160m內存。Java NIO緩沖區,JMX最長可達200米。

Java服務使用NIO大量讀寫文件,您需要使用PageCache。如前面的分析所述,這不是一個好的定量估計。

前三項總計達560米,因此您可以得出Linux物理內存不足的結論。

細心的人會發現這兩個服務器在介紹中給出。一個SWAP最多占用2.16g,另一個SWAP占用871m。然而,似乎我們的記憶差距并不大。實際上,這是由于同時實施SWAP和GC。從下圖中可以看出,SWAP的使用與長期GC同時發生。

JVM和Linux之間的詳細內存關系

JVM和Linux之間的詳細內存關系

SWAP和GC的同時發生將導致GC時間長,嚴重的JVM以及極端的服務崩潰。原因如下:當JVM執行GC時,需要遍歷相應堆分區的已用內存;如果GC,堆的某些部分交換到SWAP,并且在遍歷到此部分時需要將其交換回內存。同時,由于內存空間不足,有必要將內存中堆的另一部分切換為SWAP;在遍歷堆分區的過程中,(在極端情況下)整個堆分區將依次寫入SWAP。 Linux對SWAP的恢復滯后,我們將看到很多SWAP用法。可以通過減小堆大小或增加物理內存來解決上述問題。

因此,我們得出結論,部署Java服務的Linux系統需要避免在內存分配中使用SWAP;如何分配它取決于JVM for Java permanent generation和Java heap(新一代和老一代)在不同的場景中。 ,線程堆棧和Java NIO的內存使用情況。

2.內存泄漏問題

另一種情況是8g內存服務器,Linux使用800m,監控進程使用600m,堆大小設置為4g;系統可用內存約為2.5g,但很多SWAP也被占用。

對此問題的分析如下:

1在這種情況下,Java永久生成,Java堆(新一代和老一代),線程堆棧使用的內存基本上是固定的,因此占用過多內存的原因位于Java NIO上。

2根據以前的模型,Java NIO使用的內存主要分布在Linux內核內存的System區域和PageCache區域。查看監控記錄,如下圖所示,我們可以看到在SWAP發生之前,也就是說,當物理內存不足時,PageCache會急劇縮小。因此,位于系統區域的Java NIO緩沖區中可能會發生內存泄漏。JVM和Linux之間的詳細內存關系

JVM和Linux之間的詳細內存關系

3由于NIO的DirectByteBuffer需要稍后在GC中回收,因此連續申請DirectByteBuffer的程序通常需要調用System.gc()以避免FullGC長期失效導致舊區域中的DirectByteBuffer內存泄漏。在分析了這一點之后,可以推斷出有兩個可能的原因:首先,Java程序在必要時不調用System.gc();第二,System.gc()被禁用。

4最后,有必要檢查JVM啟動參數和Java程序的DirectByteBuffer用法。在此示例中,查看JVM啟動參數并發現啟用-XX: + DisableExplicitGC會導致System.gc()被禁用。

上一篇: 沒有了

下一篇: 沒有了

分享到:

總結

以上是生活随笔為你收集整理的Java 内存 关系_JVM和Linux之间的详细内存关系的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。