更新時間:2022-04-21 10:59:24 來源:動力節點 瀏覽1195次
JVM創建者在設計它時考慮了自動內存管理,這意味著程序員不需要擔心內存分配和內存。未使用的對象可以以透明的方式自動釋放,這非常方便,尤其是當您剛接觸JVM時。但是,即使是一般情況下,要編寫的代碼也比傳統方法少,而且不容易出錯,因為傳統方法要求您手動執行所有操作。
然而,實際情況并不像聽起來那么理想,尤其是當你在開發具有巨大流量的長壽命應用程序時。雖然在JVM中引起內存泄漏比在C中更難,但仍然有可能。選擇GC算法并將其參數化對性能也有很大的影響。而且,與任何抽象或自動化一樣,如果您希望有意識地編寫代碼(這是專業的方法),您需要了解在幕后進行了哪些工作,以便能夠預防或診斷問題。讓我們來看看一些有用的工具和技術,這些工具和技術將幫助您找到應用程序崩潰或減速的原因,而不是快速工作并能夠完成創建它的目的。
我們需要的第一件事是一段導致OutOfMemoryError的可靠代碼。OutOfMemoryError是JVM引發的異常,它通知我們內存不足。可能有許多可能的原因導致拋出此異常,您可以查看異常的原因以了解發生了什么。現在,讓我們編寫一個應用程序,它會不斷地分配內存,直到超過內存限制為止;
// file Application.scala
object Application {
def main(args: Array[String]): Unit = {
LazyList.from(0).toList
}
}
編譯一下:
scalac Application.scala
設置堆大小:
scala Application -J-Xmx10m -J-Xms10m
Xms和Xmx是JVM標志,指定應用程序的堆大小(或者簡單地說,應用程序將擁有多少內存),其中Xms代表堆的初始大小,Xmx代表最大大小。
在我們的例子中,10MB是一個足夠小的值,可以很快體驗到內存不足。我們可以看到應用程序崩潰,錯誤如下:
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
在這種情況下,問題很明顯。我們只有一個Java線程和一行代碼。當然,實際應用程序要比這復雜得多。當我們在生產中看到OutOfMemoryError時,查看堆棧跟蹤對我們沒有幫助,因為導致問題的行是相當隨機的,我們正在尋找一個分配內存且不釋放內存的代碼。我們可以在JVM內部查找問題的根源。
讓我們添加一個-XX:+HeapDumpOnOutOfMemoryError標志,它將導致在OutOfMemoryError時生成堆轉儲。
scala Application -J-Xmx10m -J-Xms10m -J-XX:+HeapDumpOnOutOfMemoryError
我們可以看到,當我們的應用程序崩潰時,生成了一個擴展名為.hprof和PID的文件。這個文件是二進制的,所以我們需要一些工具來查看里面的內容。有很多工具可以完成這項工作,即使是在線的——比如HeapHero(http://heaphero.io/),如果數據不敏感,則可以使用。
導入文件后,您可以檢查的最有用的內容是所有已分配對象的列表及其使用的內存百分比。我們可以從scala.collection.immutable不可變以及幾乎構成整個堆的整數。這與我們在項目中所做的是一致的。列表和整數是顯而易見的,因為我們創建List[int]作為結果。缺點. 這是因為Scala的LazyList使用了memorization,所以它保留了對所有元素的引用。
在磁盤空間明顯受限的環境中(例如在云中),使用-XX:+HeapDumpOnOutOfMemoryError選項時要小心。這是一個完整的堆轉儲,這意味著在OutOfMemoryError的情況下,它至少與最大堆大小一樣大。對于大的堆,這可能比分配給映像的磁盤空間大得多(因為您可能不需要太多空間,因為最好不要從服務直接寫入磁盤)。
0基礎 0學費 15天面授
有基礎 直達就業
業余時間 高薪轉行
工作1~3年,加薪神器
工作3~5年,晉升架構
提交申請后,顧問老師會電話與您溝通安排學習