首頁>Club>
8
回覆列表
  • 1 # Beaver1024

    現在的電腦,伺服器記憶體都比較大了,還存在記憶體不夠用,就需要從演算法,程式架構找原因了。需要重構和最佳化程式碼。具體怎麼做是一個大課題。

  • 2 # 道法如流

    首先與大多語言一樣,Java記憶體也分為堆記憶體(Heap)和棧記憶體(Stack)。

    Java有8種基本資料型別(int、short、byte、char、double、float、long、boolean)再加上物件引用(reference型別,它不等同於物件本身,而指向物件起始地址的引用指標。)基本資料存在棧中,物件資料存放在堆中。

    Java以下兩種記憶體異常情況:

    1. 如果執行緒請求的棧深度大於虛擬機器允許的深度,將丟擲StackOverflowError異常;2. 如果虛擬機器棧可以動態擴充套件,在擴充套件時無法申請到足夠的記憶體,就會丟擲OutOfMemoryError異常。

    如果記憶體沒有被及時回收造成記憶體佔用失控主要有以下兩種情況:

    1. 記憶體洩露(Memory Leak):程式在申請記憶體後,物件沒有被GC所回收,它始終佔用記憶體,記憶體洩漏的堆積最終會造成記憶體溢位。

    2. 記憶體溢位(Memory Overflow):程式執行過程中無法申請到足夠的記憶體而導致的一種錯誤。記憶體溢位通常發生於OLD段或Perm段垃圾回收後,仍然無記憶體空間容納新的Java物件的情況。通常都是由於記憶體洩露導致堆疊記憶體不斷增大,從而引發記憶體溢位。

    所以,如果程式大量佔用記憶體而無法釋放,要麼是記憶體洩漏要麼是記憶體溢位。排查方式包括:

    1. 程式碼除錯和日誌排查,看哪裡有迴圈引用、死迴圈、記憶體洩漏和溢位等情況。

    2. 利用Java的工具分析記憶體佔用情況:

    jinfo:可以輸出並修改執行時的java 程序的opts。

    jps:與unix上的ps類似,用來顯示本地的java程序,可以檢視本地執行著幾個java程式,並顯示他們的程序號。

    jstat:一個極強的監視VM記憶體工具。可以用來監視VM記憶體內的各種堆和非堆的大小及其記憶體使用量。

    jmap:打印出某個java程序(使用pid)記憶體內的所有"物件"的情況(如:產生那些物件,及其數量)。

    jconsole:一個java GUI監視工具,可以以圖表化的形式顯示各種資料。並可透過遠端連線監視遠端的伺服器VM。

    3. 利用專門記憶體分析工具:

    MAT(Memory Analyzer Tool)

    JProfiler

    GC Viewer

    VisualVM

    Profiler4J

    程式佔用記憶體大排查是個不容易的過程,需要一點耐心和經驗。

  • 3 # 三僡然

    首先java記憶體可以大體分為堆記憶體和棧記憶體。一般收的記憶體使用過大是指堆記憶體使用過大。一般分步驟分析。

    現在記憶體過大到底到何種程度。是否引起了GC或者FUll GC。是否影響了正常工作。

    1.明白現在記憶體有多大,可以透過工具看,和使用的記憶體比例。如果專案中需要快取很多快取,可以理解使用是合理的。如果伺服器記憶體夠大,應用可以適當調整XMX xms引數進行JVM調整。

    2.如果系統中沒有使用快取,和大物件記憶體過高,那就考慮是否有記憶體洩漏。可以使用jmap等jVM調優工具進行物件分析。然後定位過高原因修改程式碼。

    jmap -dump:format=b,file=檔名 [pid]

    dump當前系統,根據dump檔案我們可以分析當前系統中存在的記憶體問題。

    分析dump檔案的工具很多,JDK自帶的Jhat,Eclipse也有相關的外掛。

    我使用的是Eclipse Memory Analyzer,功能很強大,能夠生成各種報表,另外可以在不同的時間生成不同的dump,然後透過工具分析兩個dump的記憶體變化。

    大家專注我,我寫了好多JVM 原理和調優的文章。

  • 4 # 心靈之守護者

    僅僅java程式記憶體耗用過大這不是定位到的問題,表現是什麼(OOM了還是GC不了),具體哪個物件(或資料)導致的?導致的原因是什麼(程式碼級的)?為什麼這個原因會導致問題(設計考慮不周還是使用不當)?

    既然說到如何去做最佳化,從個人經驗來說,可分幾步來:

    發現問題:先找到需要最佳化的點是什麼,比如透過 gclog GC 發現 FGC 頻率過高,比如 OOM。定位問題:實際上就是分析問題的過程,透過藉助 JVM 工具(如jmap jstat) 或 linux 中各類 trace工具來收集相關資料(線索),再結合程式碼對問題進行分析,如有必要的可進行重現,保證定位到的問題的準確性。看哪類物件佔用的空間過大,與測試資料的規模不相對應。檢視是否有記憶體洩露。解決問題:你說的第2點,實際上是在這一步才需要做的,而且一定是針對定位到的問題採用針對性的解決方案。調優演算法。降低演算法的空間複雜度。如果有些演算法的空間複雜度可以從O(N*N)最佳化到O(N)甚至O(logN),那麼記憶體使用將降低。檢視是否有不必要的object,減少這類object。

    要想提高這方面能力,沒有捷徑,唯有不斷增加知識面(原理方面)的同時並透過排查大量案例來提高經驗值。不建議上來就是「最佳化程式碼,減少記憶體的使用」之類的,有一句話叫「過早的最佳化是萬惡之源」。

  • 5 # up隨想

    謝謝邀請,Java記憶體消耗太大,首先要檢查記憶體中的物件是不是真的必不可少,如果真的是必不可少的,那就只能擴大系統記憶體,如果檢查發現記憶體中的物件不是比不可少的,那就可以著手最佳化程式碼,將那些物件釋放(透過設定為null是一種方式),然後垃圾收集器就可以進行回收,以釋放記憶體,提高記憶體的週轉率。我們都知道Java回收物件是根據可達性分析演算法來判定物件是否可以進行回收的,也就是JVM有一些GC Root根節點,透過判斷堆記憶體中的物件是否可以到達這些節點,如果不能到達,則GC便可以進行回收,而可達的物件則不會被回收,所以我們可以透過這個特性做一些簡單判斷,然後再借助Java提供的一些實用工具和命令或其他專業分析工具進行精準分析即可。

  • 6 # 飛飛lin

    補充樓上幾位的回答,如果最後發現不是記憶體溢位,而是程式正常的需要,那可以考慮把需要的資料放入到redis去,而不是儲存在java程式的變數裡面。

    這樣子可以極大的降低記憶體記憶體消耗,又可以方便程式的叢集部署、資料共享

  • 中秋節和大豐收的關聯?
  • 傲妃多夫劇情介紹?