亚洲激情专区-91九色丨porny丨老师-久久久久久久女国产乱让韩-国产精品午夜小视频观看

溫馨提示×

溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊×
其他方式登錄
點擊 登錄注冊 即表示同意《億速云用戶服務條款》

Java中怎么使用本機內存

發布時間:2021-07-02 14:27:02 來源:億速云 閱讀:285 作者:Leah 欄目:編程語言

這篇文章將為大家詳細講解有關Java中怎么使用本機內存,文章內容質量較高,因此小編分享給大家做個參考,希望大家閱讀完這篇文章后對相關知識有一定的了解。

Java 堆和垃圾收集

Java 堆是分配了對象的內存區域。大多數 Java SE 實現都擁有一個邏輯堆,但是一些專家級 Java 運行時擁有多個堆,比如實現 Java 實時規范(Real Time Specification for Java,RTSJ)的運行時。一個物理堆可被劃分為多個邏輯扇區,具體取決于用于管理堆內存的垃圾收集(GC)算法。這些扇區通常實現為連續的本機內存塊,這些內存塊受 Java 內存管理器(包含垃圾收集器)控制。

堆的大小可以在 Java 命令行使用 -Xmx-Xms 選項來控制(mx 表示堆的***大小,ms 表示初始大小)。盡管邏輯堆(經常被使用的內存區域)可以根據堆上的對象數量和在 GC 上花費的時間而增大和縮小,但使用的本機內存大小保持不變,而且由 -Xmx 值(***堆大小)指定。大部分 GC 算法依賴于被分配為連續的內存塊的堆,因此不能在堆需要擴大時分配更多本機內存。所有堆內存必須預先保留。

保留本機內存與分配本機內存不同。當本機內存被保留時,無法使用物理內存或其他存儲器作為備用內存。盡管保留地址空間塊不會耗盡物理資源,但會阻止內存被用于其他用途。由保留從未使用的內存導致的泄漏與泄漏分配的內存一樣嚴重。

當使用的堆區域縮小時,一些垃圾收集器會回收堆的一部分(釋放堆的后備存儲空間),從而減少使用的物理內存。

對于維護 Java 堆的內存管理系統,需要更多本機內存來維護它的狀態。當進行垃圾收集時,必須分配數據結構來跟蹤空閑存儲空間和記錄進度。這些數據結構的確切大小和性質因實現的不同而不同,但許多數據結構都與堆大小成正比。

即時 (JIT) 編譯器

JIT 編譯器在運行時編譯 Java 字節碼來優化本機可執行代碼。這極大地提高了 Java 運行時的速度,并且支持 Java 應用程序以與本機代碼相當的速度運行。

字節碼編譯使用本機內存(使用方式與 gcc 等靜態編譯器使用內存來運行一樣),但 JIT 編譯器的輸入(字節碼)和輸出(可執行代碼)必須也存儲在本機內存中。包含多個經過 JIT 編譯的方法的 Java 應用程序會使用比小型應用程序更多的本機內存。

類和類加載器

Java 應用程序由一些類組成,這些類定義對象結構和方法邏輯。Java 應用程序也使用 Java 運行時類庫(比如 java.lang.String)中的類,也可以使用第三方庫。這些類需要存儲在內存中以備使用。

存儲類的方式取決于具體實現。Sun JDK 使用***生成(permanent generation,PermGen)堆區域。Java 5 的 IBM 實現會為每個類加載器分配本機內存塊,并將類數據存儲在其中。現代 Java 運行時擁有類共享等技術,這些技術可能需要將共享內存區域映射到地址空間。要理解這些分配機制如何影響您 Java 運行時的本機內存占用,您需要查閱該實現的技術文檔。然而,一些普遍的事實會影響所有實現。

從最基本的層面來看,使用更多的類將需要使用更多內存。(這可能意味著您的本機內存使用量會增加,或者您必須明確地重新設置 PermGen 或共享類緩存等區域的大小,以裝入所有類)。記住,不僅您的應用程序需要加載到內存中,框架、應用服務器、第三方庫以及包含類的 Java 運行時也會按需加載并占用空間。

Java 運行時可以卸載類來回收空間,但是只有在非常嚴酷的條件下才會這樣做。不能卸載單個類,而是卸載類加載器,隨其加載的所有類都會被卸載。只有在以下情況下才能卸載類加載器:

  • Java 堆不包含對表示該類加載器的 java.lang.ClassLoader 對象的引用。

  • Java 堆不包含對表示類加載器加載的類的任何 java.lang.Class 對象的引用。

  • 在 Java 堆上,該類加載器加載的任何類的所有對象都不再存活(被引用)。

需要注意的是,Java 運行時為所有 Java 應用程序創建的 3 個默認類加載器( bootstrapextensionapplication )都不可能滿足這些條件,因此,任何系統類(比如 java.lang.String)或通過應用程序類加載器加載的任何應用程序類都不能在運行時釋放。

即使類加載器適合進行收集,運行時也只會將收集類加載器作為 GC 周期的一部分。一些實現只會在某些 GC 周期中卸載類加載器。

也可能在運行時生成類,而不用釋放它。許多 JEE 應用程序使用 JavaServer Pages (JSP) 技術來生成 Web 頁面。使用 JSP 會為執行的每個 .jsp 頁面生成一個類,并且這些類會在加載它們的類加載器的整個生存期中一直存在 —— 這個生存期通常是 Web 應用程序的生存期。

另一種生成類的常見方法是使用 Java 反射。反射的工作方式因 Java 實現的不同而不同,但 Sun 和 IBM 實現都使用了這種方法,我馬上就會講到。

當使用 java.lang.reflect API 時,Java 運行時必須將一個反射對象(比如 java.lang.reflect.Field)的方法連接到被反射到的對象或類。這可以通過使用 Java 本機接口(Java Native Interface,JNI)訪問器來完成,這種方法需要的設置很少,但是速度緩慢。也可以在運行時為您想要反射到的每種對象類型動態構建一個類。后一種方法在設置上更慢,但運行速度更快,非常適合于經常反射到一個特定類的應用程序。

Java 運行時在最初幾次反射到一個類時使用 JNI 方法,但當使用了若干次 JNI 方法之后,訪問器會膨脹為字節碼訪問器,這涉及到構建類并通過新的類加載器進行加載。執行多次反射可能導致創建了許多訪問器類和類加載器。保持對反射對象的引用會導致這些類一直存活,并繼續占用空間。因為創建字節碼訪問器非常緩慢,所以 Java 運行時可以緩存這些訪問器以備以后使用。一些應用程序和框架還會緩存反射對象,這進一步增加了它們的本機內存占用。

JNI

JNI 支持本機代碼(使用 C 和 C++ 等本機編譯語言編寫的應用程序)調用 Java 方法,反之亦然。Java 運行時本身極大地依賴于 JNI 代碼來實現類庫功能,比如文件和網絡 I/O。JNI 應用程序可能通過 3 種方式增加 Java 運行時的本機內存占用:

  • JNI 應用程序的本機代碼被編譯到共享庫中,或編譯為加載到進程地址空間中的可執行文件。大型本機應用程序可能僅僅加載就會占用大量進程地址空間。

  • 本機代碼必須與 Java 運行時共享地址空間。任何本機代碼分配或本機代碼執行的內存映射都會耗用 Java 運行時的內存。

  • 某些 JNI 函數可能在它們的常規操作中使用本機內存。GetTypeArrayElementsGetTypeArrayRegion 函數可以將 Java 堆數據復制到本機內存緩沖區中,以供本機代碼使用。是否復制數據依賴于運行時實現。(IBM Developer Kit for Java 5.0 和更高版本會進行本機復制)。通過這種方式訪問大量 Java 堆數據可能會使用大量本機堆。

NIO

Java 1.4 中添加的新 I/O (NIO) 類引入了一種基于通道和緩沖區來執行 I/O 的新方式。就像 Java 堆上的內存支持 I/O 緩沖區一樣,NIO 添加了對直接 ByteBuffer 的支持(使用 java.nio.ByteBuffer.allocateDirect() 方法進行分配), ByteBuffer 受本機內存而不是 Java 堆支持。直接 ByteBuffer 可以直接傳遞到本機操作系統庫函數,以執行 I/O — 這使這些函數在一些場景中要快得多,因為它們可以避免在 Java 堆與本機堆之間復制數據。

對于在何處存儲直接 ByteBuffer 數據,很容易產生混淆。應用程序仍然在 Java 堆上使用一個對象來編排 I/O 操作,但持有該數據的緩沖區將保存在本機內存中,Java 堆對象僅包含對本機堆緩沖區的引用。非直接 ByteBuffer 將其數據保存在 Java 堆上的 byte[] 數組中。下圖展示了直接與非直接 ByteBuffer 對象之間的區別:

直接與非直接 java.nio.ByteBuffer 的內存拓撲結構
Java中怎么使用本機內存

直接 ByteBuffer 對象會自動清理本機緩沖區,但這個過程只能作為 Java 堆 GC 的一部分來執行,因此它們不會自動響應施加在本機堆上的壓力。GC 僅在 Java 堆被填滿,以至于無法為堆分配請求提供服務時發生,或者在 Java 應用程序中顯式請求它發生(不建議采用這種方式,因為這可能導致性能問題)。

發生垃圾收集的情形可能是,本機堆被填滿,并且一個或多個直接 ByteBuffers 適合于垃圾收集(并且可以被釋放來騰出本機堆的空間),但 Java 堆幾乎總是空的,所以不會發生垃圾收集。

線程

應用程序中的每個線程都需要內存來存儲器堆棧(用于在調用函數時持有局部變量并維護狀態的內存區域)。每個 Java 線程都需要堆棧空間來運行。根據實現的不同,Java 線程可以分為本機線程和 Java 堆棧。除了堆棧空間,每個線程還需要為線程本地存儲(thread-local storage)和內部數據結構提供一些本機內存。

堆棧大小因 Java 實現和架構的不同而不同。一些實現支持為 Java 線程指定堆棧大小,其范圍通常在 256KB 到 756KB 之間。

盡管每個線程使用的內存量非常小,但對于擁有數百個線程的應用程序來說,線程堆棧的總內存使用量可能非常大。如果運行的應用程序的線程數量比可用于處理它們的處理器數量多,效率通常很低,并且可能導致糟糕的性能和更高的內存占用。

關于Java中怎么使用本機內存就分享到這里了,希望以上內容可以對大家有一定的幫助,可以學到更多知識。如果覺得文章不錯,可以把它分享出去讓更多的人看到。

向AI問一下細節

免責聲明:本站發布的內容(圖片、視頻和文字)以原創、轉載和分享為主,文章觀點不代表本網站立場,如果涉及侵權請聯系站長郵箱:is@yisu.com進行舉報,并提供相關證據,一經查實,將立刻刪除涉嫌侵權內容。

AI

巴南区| 观塘区| 吉木萨尔县| 合肥市| 迁安市| 调兵山市| 固镇县| 阳高县| 久治县| 巴青县| 长沙县| 唐山市| 布尔津县| 保康县| 双鸭山市| 连城县| 仙桃市| 师宗县| 博乐市| 法库县| 灵山县| 连州市| 筠连县| 南溪县| 沙洋县| 乳山市| 桓台县| 金山区| 长兴县| 河曲县| 龙海市| 政和县| 买车| 汶川县| 上饶县| 淮阳县| 徐水县| 措美县| 濉溪县| 宁城县| 莱西市|