搜尋
首頁Javajava教程JVM記憶體管理------雜談(藉此也論一論obj=null)

作為一個程序猿,修練的過程就猶如玄幻小說中的主角,不僅需要練習各種武技,內氣的修練的一樣重要。雖然武技可以迅速的提升主角的實力,但是在內氣太差的情況下,根本發揮不出武技的十之一二。
因此,在介紹過設計模式這一類外功之後,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)!


陳述
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
JVM如何促進Java的'寫作一次,在任何地方運行”(WORA)功能?JVM如何促進Java的'寫作一次,在任何地方運行”(WORA)功能?May 02, 2025 am 12:25 AM

JVM通過字節碼解釋、平台無關的API和動態類加載實現Java的WORA特性:1.字節碼被解釋為機器碼,確保跨平台運行;2.標準API抽像操作系統差異;3.類在運行時動態加載,保證一致性。

Java的較新版本如何解決平台特定問題?Java的較新版本如何解決平台特定問題?May 02, 2025 am 12:18 AM

Java的最新版本通過JVM優化、標準庫改進和第三方庫支持有效解決平台特定問題。 1)JVM優化,如Java11的ZGC提升了垃圾回收性能。 2)標準庫改進,如Java9的模塊系統減少平台相關問題。 3)第三方庫提供平台優化版本,如OpenCV。

說明JVM執行的字節碼驗證的過程。說明JVM執行的字節碼驗證的過程。May 02, 2025 am 12:18 AM

JVM的字節碼驗證過程包括四個關鍵步驟:1)檢查類文件格式是否符合規範,2)驗證字節碼指令的有效性和正確性,3)進行數據流分析確保類型安全,4)平衡驗證的徹底性與性能。通過這些步驟,JVM確保只有安全、正確的字節碼被執行,從而保護程序的完整性和安全性。

平台獨立性如何簡化Java應用程序的部署?平台獨立性如何簡化Java應用程序的部署?May 02, 2025 am 12:15 AM

Java'splatFormIndepentEncealLowsApplicationStorunonAnyOperatingsystemwithajvm.1)singleCodeBase:writeandeandcompileonceforallplatforms.2)easileupdates:updatebybytecodeforsimultanane deployment.3)testOnOneOnePlatForforurouniverSalpeforuluniverSalpehavior formafforulululyiversalivernave.444.44.444

Java的平台獨立性如何隨著時間的流逝而發展?Java的平台獨立性如何隨著時間的流逝而發展?May 02, 2025 am 12:12 AM

Java的平台獨立性通過JVM、JIT編譯、標準化、泛型、lambda表達式和ProjectPanama等技術不斷增強。自1990年代以來,Java從基本的JVM演進到高性能的現代JVM,確保了代碼在不同平台的一致性和高效性。

在Java應用程序中緩解平台特定問題的策略是什麼?在Java應用程序中緩解平台特定問題的策略是什麼?May 01, 2025 am 12:20 AM

Java如何緩解平台特定的問題? Java通過JVM和標準庫來實現平台無關性。 1)使用字節碼和JVM抽像操作系統差異;2)標準庫提供跨平台API,如Paths類處理文件路徑,Charset類處理字符編碼;3)實際項目中使用配置文件和多平台測試來優化和調試。

Java的平台獨立性與微服務體系結構之間有什麼關係?Java的平台獨立性與微服務體系結構之間有什麼關係?May 01, 2025 am 12:16 AM

java'splatformentenceenhancesenhancesmicroservicesharchitecture byferingDeploymentFlexible,一致性,可伸縮性和便攜性。 1)DeploymentFlexibilityAllowsibilityAllowsOllowsOllowSorlowsOllowsOllowsOllowSeStorunonAnyPlatformwithajvM.2)penterencyCrossServAccAcrossServAcrossServiCessImplifififiesDeevelopmentandeDe

GRAALVM與Java的平台獨立目標有何關係?GRAALVM與Java的平台獨立目標有何關係?May 01, 2025 am 12:14 AM

GraalVM通過三種方式增強了Java的平台獨立性:1.跨語言互操作,允許Java與其他語言無縫互操作;2.獨立的運行時環境,通過GraalVMNativeImage將Java程序編譯成本地可執行文件;3.性能優化,Graal編譯器生成高效的機器碼,提升Java程序的性能和一致性。

See all articles

熱AI工具

Undresser.AI Undress

Undresser.AI Undress

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

AI Clothes Remover

AI Clothes Remover

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

Undress AI Tool

Undress AI Tool

免費脫衣圖片

Clothoff.io

Clothoff.io

AI脫衣器

Video Face Swap

Video Face Swap

使用我們完全免費的人工智慧換臉工具,輕鬆在任何影片中換臉!

熱工具

SublimeText3漢化版

SublimeText3漢化版

中文版,非常好用

VSCode Windows 64位元 下載

VSCode Windows 64位元 下載

微軟推出的免費、功能強大的一款IDE編輯器

Dreamweaver CS6

Dreamweaver CS6

視覺化網頁開發工具

Dreamweaver Mac版

Dreamweaver Mac版

視覺化網頁開發工具

SublimeText3 Linux新版

SublimeText3 Linux新版

SublimeText3 Linux最新版