[英]Java: flushing memory out to disk
假設我有一個 Java 應用程序,它大致執行以下操作:
有沒有辦法鼓勵或強制 JVM 在長時間空閑時將其內存刷新到磁盤? (例如,在第 2 步結束時,進行一些函數調用,有效地說“嘿 JVM!我要睡一會兒了。”)
我不介意使用大量虛擬內存,但物理內存在我使用的機器上非常寶貴,因為有很多后台進程。
我認為操作系統應該處理這個問題。
否則,您可以在初始化后手動將應用程序存儲到磁盤或數據庫,然后從該數據進行更快的初始化,也許吧?
與其讓您的程序閑置並耗盡資源,為什么不使用 cron 對其進行調度? 或者更好的是,因為您使用的是 Java,所以使用Quartz 來安排它? 盡最大努力緩存冗長的初始化過程的元素,這樣您就不必在每次計划任務運行時付出很大的代價。
您必須確保的第一件事是您的對象是可垃圾回收的。 但這只是第一步。
其次,JVM 使用的內存可能根本不會返還給操作系統。
例如。 假設您有 100mb 的 java 對象,您的 VM 大小約為 100mb。 在垃圾收集之后,您可以將堆使用量減少到 10mb,但 VM 將保持在 100mb 左右。 此策略用於允許 VM 為新對象提供可用內存。
要讓應用程序將“物理”內存返回給系統,您必須檢查您的 VM 是否支持這樣的事情。
還有一些額外的VM 選項可以讓您的應用程序向操作系統返回更多內存:
-XX:MaxHeapFreeRatio=70 GC 后空閑堆的最大百分比,以避免收縮。
-XX:MinHeapFreeRatio=40 GC 后堆空閑的最小百分比以避免擴展。
根據我自己的解釋,如果使用這些選項,VM 將在低於 70% 時推卸。 但坦率地說,我不知道是只有堆會收縮並返回到操作系統,還是只在VM內部收縮。
有關熱內存管理工作的完整描述,請參見:
HotSpot GC 描述:Java HotSpot 虛擬機中的內存管理白皮書: https : //www.oracle.com/technetwork/java/javase/memorymanagement-whitepaper-150215.pdf
拜托,拜托。 試一試並讓我們知道這是否有效地減少了內存消耗。
至少可以說這是一個黑客,但假設您使用的是 Win32 並且如果您准備放棄可移植性 - 編寫一個調用SetProcessWorkingSetSize的小 DLL 並使用 JNI 調用它。 這允許您向操作系統建議WS 大小應該是什么。 您甚至可以指定 -1,在這種情況下,操作系統將嘗試盡可能多地分頁。
假設這是一個等待請求的服務器,你能這樣做嗎?
這意味着內存密集型 Worker 對象會從內存中卸載(當 gc 下次運行時,您可以通過在將 Worker 對象設置為 null 后調用 System.gc() 來鼓勵 gc 運行),但是由於您保存了它的狀態,您可以從磁盤重新加載它並讓它完成工作而無需再次進行初始化。 如果它需要每“x”小時運行一次,您可以在 Server 類中放置一個 java.util.Timer 而不是偵聽套接字。
編輯:還有一個 JVM 選項 -Xmx 用於設置 JVM 堆的最大大小。 在這種情況下這可能沒有幫助,但只是想我會把它扔在那里。
這不是頁面文件的用途嗎? 如果您的 JVM 閑置了一段時間並且不訪問它的內存頁面。 它很可能會被分頁,因此不會使用太多的實際 RAM。
但是你可以做一件事......大多數守護程序都有一個啟動階段(它們解析文件並創建數據結構等)和一個運行階段,它們使用在啟動時創建的對象。 如果 JVM 被允許,它將在第二階段啟動而不進行垃圾收集,這可能會導致進程的大小增長,然后在進程的生命周期內保持那么大(因為 GC 從不/很少減少實際大小)過程)。
如果您確保在下一個階段開始之前在程序生命周期的每個不同階段分配的所有內存都是可 GC 的,那么您可以使用 -Xmx 設置來強制降低進程的最大大小,並使您的程序在階段之間不斷進行 GC。 我以前這樣做過並取得了一些成功。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.