作為一個程序猿,修練的過程就猶如玄幻小說中的主角,不僅需要練習各種武技,內氣的修練的一樣重要。雖然武技可以迅速的提升主角的實力,但是在內氣太差的情況下,根本發揮不出武技的十之一二。
因此,在介紹過設計模式這一類外功之後,LZ就直接轉戰內氣修煉,和各位猿友探討一下JVM的內容。
本來這一章應該是介紹與GC相關的內容,不過在此之前,LZ準備先和各位探討一下一個程式設計的小技巧。當然,這個小技巧其實也是跟GC密切相關的。
不知道各位猿友有沒看過一些JAVA記憶體相關的文章,裡面在羅列建議的時候,常常會寫出這樣一條建議。
第XX條、請在使用完物件之後,顯示的將物件設為null。
原話不一定如此,但意思是一樣的。話裡所描述的意思,就是說我們以後寫程式應該這麼寫。
Object obj = new Object(); //to do something obj = null;
這段程式碼有點C/C++的風格,obj=null取代了C/C++中的delete obj或是free(obj),相當於在提示我們,就算有了GC,我們也要像沒有GC一樣,使用完物件就得將其賦為空值。
首先,LZ這裡要說明的是,將obj賦為空值,與C/C++中的delete其實有著天壤之別,LZ之所以說它們代替了delete和free,僅僅是因為它們出現在程式碼中的位置類似而已。
obj=null只做了一件事,就是將obj這個引用變數與new Object()所創造的實例的關聯斷開,實際上,實例所佔用的記憶體空間依然沒有釋放。
在提出這個建議的時候,很多部落客或書籍的作者(因為有不少部落客估計也是從書上看的)的本意,是想盡快消除引用與實例的關聯,從而誘發GC在進行垃圾回收時,將實例所佔用的記憶體釋放。在某些時候,這麼做也是為了消除記憶體外洩。
LZ個人覺得,許多部落客或是書籍作者,提出這個建議的初衷,主要是針對一些沒有接觸過GC原理以及記憶體管理的程式猿而建議的,因為在不明白相關知識的前提下,很容易掌握不好變數的作用域,從而導致不必要的記憶體浪費(個人覺得這個並不是主要目的,因為只要沒有發生記憶體洩露,記憶體終究是要被GC釋放的),甚至是記憶體洩露。
所以為了安全起見,有些高人們就提出了這麼一個建議。
有鑑於此,LZ個人覺得,在各位掌握了相關知識之後,完全可以忽略這個建議,而且這麼做明顯會降低代碼的清晰度以及增加編碼的負擔,然而所換來的好處,卻只是為了避免那根本不一定存在的記憶體外洩。
這裡解釋一下為何在有些時候不將物件賦為空值會造成記憶體洩露,我們考慮下面一段程式碼。
import java.util.Arrays; public class Stack { private static final int INIT_SIZE = 10; private Object[] datas; private int size; public Stack() { super(); datas = new Object[INIT_SIZE]; } public void push(Object data){ if (size == datas.length) { extend(); } datas[size++] = data; } public Object pop(){ if (size == 0) { throw new IndexOutOfBoundsException("size is zero"); } return datas[--size]; } private void extend(){ datas = Arrays.copyOf(datas, 2 * size + 1); } }
這段程式碼是一個簡單的長度可伸縮的棧實現,在你寫一段測試程式碼去測試它的時候,會發現它毫無問題。但是不好意思,這裡面就有一個明顯的“內存洩漏”,這就是因為一些物件或說引用沒有設定為空值所造成的。
如果你還沒看出來,LZ稍微提示一下,各位就會意識到了。這段程式碼裡面,陣列裡的物件只會無限增長,而不會隨著堆疊中元素的彈出而減少,減少的只是對外展示的堆疊的大小size。考慮一個極端的場景,假設你曾經往棧中放入了100萬個對象,最後使用了99萬9千9百9十9個,從外部看來,棧中還只剩一個可用對象了,但是我們的堆疊依然持有著100萬個物件的引用。如果JVM可以活過來的話,想必一定會把你蹂躪到死的。
我們缺少的就是將物件賦為null值的那一步,所以pop方法應該改為下面的方式,而且各位可以去看一下ArrayList中remove方法的源碼,也是類似的思路。
public Object pop(){ if (size == 0) { throw new IndexOutOfBoundsException("size is zero"); } Object data = datas[--size]; datas[size] = null; return data; }
这个内存泄露是非常隐蔽的,而且实际使用当中不一定就能发现,因为随着Stack对象的回收,整个数组也会被回收,到时内存泄露就被掩盖了。
所以个人觉得上述的那个建议是完全没有必要的,就算遵从了上面的建议,如果对内存管理不熟悉的话,也不会想到上面这个代码中的问题。如果想彻底的避免内存泄露的发生,机械式的主动将对象赋为空值,并不是一个可以从根本上解决问题的办法。
真正能够解决问题的办法,就是掌握好GC的策略与原理,定义一个变量时多注意变量的作用域,如此才可以更好的避免内存泄露。
所以学好GC原理还是很有必要的,希望准备走JAVA之路的朋友,尤其是从培训机构出来的猿友们(此处没有鄙视培训机构出来的猿友们的意思,因为LZ本人也是半路出家,从培训机构走上编程之路的程序猿之一),一定不要只专注于各个框架的使用以及业务的深入,虽然这些事很有必要,但并不是全部。
follow me and go the memory world 吧(语法都是浮云)。
以上就是JVM内存管理------杂谈(借此也论一论obj=null)的内容,更多相关内容请关注PHP中文网(www.php.cn)!

本文討論了使用咖啡因和Guava緩存在Java中實施多層緩存以提高應用程序性能。它涵蓋設置,集成和績效優勢,以及配置和驅逐政策管理最佳PRA

Java的類上載涉及使用帶有引導,擴展程序和應用程序類負載器的分層系統加載,鏈接和初始化類。父代授權模型確保首先加載核心類別,從而影響自定義類LOA

本文使用lambda表達式,流API,方法參考和可選探索將功能編程集成到Java中。 它突出顯示了通過簡潔性和不變性改善代碼可讀性和可維護性等好處

本文討論了使用JPA進行對象相關映射,並具有高級功能,例如緩存和懶惰加載。它涵蓋了設置,實體映射和優化性能的最佳實踐,同時突出潛在的陷阱。[159個字符]

本文討論了使用Maven和Gradle進行Java項目管理,構建自動化和依賴性解決方案,以比較其方法和優化策略。

本文使用選擇器和頻道使用單個線程有效地處理多個連接的Java的NIO API,用於非阻滯I/O。 它詳細介紹了過程,好處(可伸縮性,性能)和潛在的陷阱(複雜性,

本文使用Maven和Gradle之類的工具討論了具有適當的版本控制和依賴關係管理的自定義Java庫(JAR文件)的創建和使用。

本文詳細介紹了用於網絡通信的Java的套接字API,涵蓋了客戶服務器設置,數據處理和關鍵考慮因素,例如資源管理,錯誤處理和安全性。 它還探索了性能優化技術,我


熱AI工具

Undresser.AI Undress
人工智慧驅動的應用程序,用於創建逼真的裸體照片

AI Clothes Remover
用於從照片中去除衣服的線上人工智慧工具。

Undress AI Tool
免費脫衣圖片

Clothoff.io
AI脫衣器

AI Hentai Generator
免費產生 AI 無盡。

熱門文章

熱工具

WebStorm Mac版
好用的JavaScript開發工具

mPDF
mPDF是一個PHP庫,可以從UTF-8編碼的HTML產生PDF檔案。原作者Ian Back編寫mPDF以從他的網站上「即時」輸出PDF文件,並處理不同的語言。與原始腳本如HTML2FPDF相比,它的速度較慢,並且在使用Unicode字體時產生的檔案較大,但支援CSS樣式等,並進行了大量增強。支援幾乎所有語言,包括RTL(阿拉伯語和希伯來語)和CJK(中日韓)。支援嵌套的區塊級元素(如P、DIV),

Dreamweaver CS6
視覺化網頁開發工具

PhpStorm Mac 版本
最新(2018.2.1 )專業的PHP整合開發工具

MinGW - Minimalist GNU for Windows
這個專案正在遷移到osdn.net/projects/mingw的過程中,你可以繼續在那裡關注我們。 MinGW:GNU編譯器集合(GCC)的本機Windows移植版本,可自由分發的導入函式庫和用於建置本機Windows應用程式的頭檔;包括對MSVC執行時間的擴展,以支援C99功能。 MinGW的所有軟體都可以在64位元Windows平台上運作。