0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復
登錄后你可以
  • 下載海量資料
  • 學習在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認識你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

程序員眼里的內(nèi)存(中)

jf_78858299 ? 來源:碼農(nóng)的荒島求生 ? 作者:碼農(nóng)的荒島求生 ? 2023-02-24 14:09 ? 次閱讀

本節(jié)是操作系統(tǒng)系列教程的第三篇文章,屬于操作系統(tǒng)第一章即基礎(chǔ)篇,在真正開始操作系統(tǒng)相關(guān)章節(jié)前在這一部分回顧一些重要的主題,以下是目錄,由于本文篇幅較多因此會按上篇、中篇、下篇三次發(fā)布,目錄中黑體為本篇內(nèi)容。


什么是內(nèi)存

C/C++內(nèi)存模型

**堆區(qū)與棧區(qū)的本質(zhì)

**

**JavaPython等內(nèi)存模型

**

**Java內(nèi)存模型

**

**Jave中的堆區(qū)與棧區(qū)是如何實現(xiàn)的

**

Python內(nèi)存模型

指針與引用

進程的內(nèi)存模型

幻想大師-操作系統(tǒng)

總結(jié)


堆與棧的本質(zhì)是什么

編程語言中,堆區(qū)和棧區(qū)本質(zhì)上都是內(nèi)存,因此二者在本質(zhì)上沒有任何區(qū)別,只不過這兩塊內(nèi)存的使用方式是不一樣的。

在數(shù)據(jù)結(jié)構(gòu)與算法中,我們也有堆和棧的概念,但那里指的不是內(nèi)存,而是兩種數(shù)據(jù)結(jié)構(gòu)。

你可能會想,我們?yōu)槭裁匆M盡心力的提出堆和棧這兩個概念呢?之所以需要區(qū)分兩種內(nèi)存用法,根源在于: 內(nèi)存是有限的 。

如果計算機內(nèi)存是無限的,那么我們根本就不用這么麻煩的給內(nèi)存劃分兩個區(qū)域,在其中的一個區(qū)域中這樣使用內(nèi)存,另一區(qū)域那樣使用內(nèi)存,這些都是不需要的。即使在今天PC內(nèi)存普遍都在8G、16G,這依然是不夠的,因此我們需要合理的來安排內(nèi)存的使用,堆和棧就是為達到這一目的而采用的技術(shù)。

你會發(fā)現(xiàn)棧其實是一種非常巧妙的內(nèi)存使用方法。函數(shù)調(diào)用完成后,函數(shù)運行過程中占用的內(nèi)存就會被釋放掉,這樣,只要程序員代碼寫的合理(棧幀不至于過大),那我們程序就可以一直運行下去,而不會出現(xiàn)內(nèi)存不足的現(xiàn)象。程序員在棧區(qū)不需要擔心內(nèi)存分配釋放問題,因為這一切都是自動進行的。而如果程序員想自己控制內(nèi)存,那么可以選擇在堆上進行內(nèi)存分配。因此這里提供了兩種選擇,一種是“自動的”,一種是“手動的”,目的都是在合理使用內(nèi)存的同時提供給程序員最大的靈活性。

堆和棧是計算機科學中很優(yōu)秀的設(shè)計思想,這種設(shè)計思想充分的體現(xiàn)了計算機如何合理且靈活的使用有限資源。

堆區(qū)和棧區(qū)對C/C++程序員來說就是實實在在的內(nèi)存,而對于Java、Python等語言的程序員來說又該如何理解內(nèi)存呢?

Java、Python等內(nèi)存模型

當Java、Python等語言的程序在執(zhí)行時其解釋器的內(nèi)存布局同樣如下圖所示,我們之前講過,解釋器也是一個C/C++程序,因此這里的代碼段包含的是解釋器的實現(xiàn)代碼而不是Java、Python等代碼,這一點大家一定要注意。

"C/C++程序員面對的是實實在在的物理內(nèi)存,Java、Python等程序面對的是解釋器。"

C/C++分配內(nèi)存是直接在物理內(nèi)存中進行的,而Java、Python等程序是將內(nèi)存分配請求交給解釋器,解釋器再去物理內(nèi)存上進行分配。希望大家務必理解這一點。

Java、Python等程序員是看不到如下圖所示的內(nèi)存布局的,因為這一切都是解釋器才能看到的,解釋器對Java、Python等程序員屏蔽了這些。Java、Python等程序員也無需關(guān)心解釋器的內(nèi)存布局。

Java、Python等程序的一大優(yōu)點就是內(nèi)存的自動化管理,而C/C++程序員需要自己來管理從堆上分配的內(nèi)存。內(nèi)存管理這一項工作在Java、Python等程序中被解釋器接管了,解釋器的這項功能被稱為“垃圾回收器”。

在非C/C++語言中,我們來看兩個有代表性的語言,首先我們看一下Java。

Java內(nèi)存模型

Java的內(nèi)存模型中同樣有棧和堆這樣的概念,如下圖所示,在Java函數(shù)中我們定義的內(nèi)置數(shù)據(jù)類型比如int a = 0,是直接存放在棧上的,引用類型,也就是用new關(guān)鍵字定義的變量是分配在堆上的。和C/C++一樣,每個Java函數(shù)在執(zhí)行時都有自己的棧幀。隨著函數(shù)的調(diào)用,棧不斷的擴大。當函數(shù)調(diào)用完畢后棧幀被回收,在堆上分配的變量依然可以被后續(xù)函數(shù)使用。Java程序員無需像C/C++程序員一樣需要關(guān)心內(nèi)存回收的問題,這一切都是Java的解釋器JVM來管理的。

在用法上Java中的堆和棧和C/C++是一樣的,只不過Java程序員無需關(guān)心內(nèi)存的釋放問題。但是好奇的同學可能會問,C/C++中的堆和棧我已經(jīng)清楚了,因為C/C++程序運行時在內(nèi)存中的樣子已經(jīng)在《C/C++內(nèi)存模型》這一小節(jié)中詳細的講述了,那么Java中的堆和棧在內(nèi)存中是什么樣子的呢,就是和上圖一樣嗎?要回答這個問題,就要涉及到Java中的堆和棧是如何實現(xiàn)的。

Java中的堆和棧是如何實現(xiàn)的

如果你自己設(shè)計過一門語言的話,你應該會很清楚這個問題。

我們先回答上一節(jié)中提到的問題,那就是Java中的堆和棧就是如上圖所示的那樣嗎?是這樣的,作為Java程序員在寫代碼時腦海里有上面這張圖基本上就夠用了。但是,Java中的堆和棧不同于C/C++當中的堆和棧。

我們已經(jīng)知道Java中的內(nèi)存管理其實是解釋器JVM來搞定的,作為C/C++程序,JVM的內(nèi)存布局就如下圖所示。

一般情況下,當JVM運行一個Java函數(shù)時需要在堆上創(chuàng)建出Java函數(shù)的棧幀,然后把這些棧幀放入棧中(這里的棧指的是具有先進后出性質(zhì)的數(shù)據(jù)結(jié)構(gòu))。希望大家不要被這句話繞暈,這里出現(xiàn)了兩個“?!保呛x完全不同。

  • Java棧幀:指的是上圖中我們看到的棧。

  • 棧幀放入到棧:我們在數(shù)據(jù)結(jié)構(gòu)課程中都學過棧,棧有push和pop兩種操作,把棧幀放入棧指的是把棧幀push到JVM所持有的棧這種數(shù)據(jù)結(jié)構(gòu)當中,以此來模擬C/C++程序執(zhí)行過程中函數(shù)棧幀先進后出的這種性質(zhì),當一個Java函數(shù)被執(zhí)行完畢后,JVM pop掉該函數(shù)的棧幀。

    如果你想在代碼級別來理解這個過程,大體上可以參考下面的代碼,注意JVM是C/C++程序,這里的代碼是一個極其簡單的描述。你可以看到如何組織棧幀完全是JVM設(shè)計者來決定的,只要棧幀具備先進后出的性質(zhì)就可以。

void RunJavaFunction(JVM* jvm, string javaFunction) {


    // 在堆上申請一塊空間,用于存放java棧幀
    stackFrame* frame = (stackFrame*) malloc(sizeof(stackFrame));

    // 把要使用的棧幀push到JVM的函數(shù)調(diào)用棧中
    jvm->stack->push(frame);

    // 在申請的棧幀上執(zhí)行Java函數(shù)
    run(javaFunction, frame);

    // 執(zhí)行完畢后pop掉該函數(shù)棧幀
    jvm->stack->pop();
}

JVM會在自己的堆中為用new修飾的對象創(chuàng)建內(nèi)存,這里的堆就是如上圖所示的堆,是可以要記住JVM是一個C/C++程序,JVM看到的堆才是如上圖所示的那樣。所以你會發(fā)現(xiàn),一般情況下, Java中的棧和Java對象都是JVM在自己的堆上分配出來的 ,這就是Java中堆和棧是如何實現(xiàn)的。

在講解完Java的內(nèi)存模型后,我們來看一下Python的。

Python內(nèi)存模型

Python的內(nèi)存模型和Java其實是類似的,Java程序員腦海中的那張圖同樣適用于Python程序員。

Python語言中的解釋器比較多,比如CPython,PyPy等,在這里我們以Python默認的解釋器CPython為例來說明,我們已經(jīng)知道了解釋器其實也是一個C程序,CPython也不例外,下圖左側(cè)就是我們已經(jīng)熟悉的C/C++內(nèi)存布局,我們把堆區(qū)放大,如下圖右側(cè)所示。我們可以看到Python的解釋器把自己的堆區(qū)劃分成了兩部分,分別是Object-specific memory區(qū)域,以及Python core區(qū)域:

Object-specific memory這個區(qū)域?qū)iT用來存放PyObject。你也許已經(jīng)知道了,Python中所有的數(shù)據(jù)類型比如int,dict,str等都是一個對象,叫做PyObject。當我們在Python中創(chuàng)建一個變量比如dict時,CPython就會在堆區(qū)的上半部分(Object-specific memory)中分配一塊內(nèi)存,創(chuàng)建一個PyObject,這個PyObject用來存放我們的dict。

Python core:所有非PyObject的內(nèi)存請求都在這里分配的。

所以你會發(fā)現(xiàn),Python中所有的內(nèi)存同樣是解釋器在自己的堆上分配的。

聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學習之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報投訴
  • JAVA
    +關(guān)注

    關(guān)注

    19

    文章

    2967

    瀏覽量

    104758
  • 堆棧
    +關(guān)注

    關(guān)注

    0

    文章

    182

    瀏覽量

    19762
  • python
    +關(guān)注

    關(guān)注

    56

    文章

    4797

    瀏覽量

    84690
收藏 人收藏

    評論

    相關(guān)推薦

    程序員需要學什么,微軟資深程序員學習手冊面試寶典資料

    程序員是現(xiàn)在比較吃香的工作。程序員工資高還不需要和復雜的社會打交道。那么怎么成為一名程序員?當程序員需要學什么?
    發(fā)表于 03-22 11:54 ?30次下載

    “菜鳥”程序員和“大神”程序員到底有什么區(qū)別

    現(xiàn)在社會上有很多程序員,那您是否可想過程序員為什么會有不同的水平?你又是哪一類的程序員?“菜鳥”程序員和“大神”程序員差在哪里?
    的頭像 發(fā)表于 05-14 08:48 ?3730次閱讀

    這可能就是程序員最大的悲哀

    這個繁榮的行業(yè),只要你自己不水,可以衣食無憂,努努力還能buffer加成,成為別人眼里很酷的那種人,沒多少行業(yè)如程序員起薪高,也沒多少行業(yè)如程序員漲薪快,沒多少行業(yè)如程序員這般智力密集
    的頭像 發(fā)表于 12-07 15:47 ?1232次閱讀

    程序員如何定義

    當了幾年的程序員了,一直都在想一個問題,什么是程序員程序員應該做好那些事情,什么樣的程序員是有素質(zhì)的程序員?什么樣的
    的頭像 發(fā)表于 12-18 14:15 ?2629次閱讀

    菜鳥程序員和大神程序員的差距

    剛剛走出就業(yè)的程序員,技術(shù)是剛剛起步的基點。那下面我們就聊一聊有關(guān)技術(shù)的東西。首先請您先想想這幾個問題。現(xiàn)在社會上有很多程序員,CSDN就是我們程序員的家,那您是否可想過程序員為什么會
    的頭像 發(fā)表于 06-03 15:56 ?2536次閱讀

    什么是程序員

    當了幾年的程序員了,一直都在想一個問題,什么是程序員,程序員應該做好那些事情,什么樣的程序員是有素質(zhì)的程序員?什么樣的
    的頭像 發(fā)表于 06-04 16:21 ?9006次閱讀

    程序員的未來

    程序員出路在何方程序員 創(chuàng)業(yè)如果你是程序員,也想創(chuàng)業(yè),看看我說的。
    的頭像 發(fā)表于 06-12 17:29 ?2956次閱讀

    為什么要成為高級程序員

    程序員到高級程序員的職業(yè)生涯要經(jīng)歷以下幾個階段:初級程序員、中級程序員、最后是高級程序員
    的頭像 發(fā)表于 07-11 16:51 ?2439次閱讀

    普通程序員和高級程序員有哪些區(qū)別

    從工作的方面來說,普通程序員和高級程序員一般有下面幾個區(qū)別:
    的頭像 發(fā)表于 09-08 10:47 ?3783次閱讀

    如何定義程序員

    多年以來,黑程序員一直是一項廣大人民群眾喜聞樂見的娛樂活動,我們不僅黑程序員,程序員也喜歡自黑,如此一來,大家好像都覺得黑程序員是一項天經(jīng)地義的事情了,然而事實上,的確是的。
    的頭像 發(fā)表于 10-28 17:05 ?2736次閱讀

    JAVA程序員和C程序員有什么區(qū)別

    1、知道JAVA程序員和C程序員的差別嗎?食堂里,吃完飯就走的是JAVA程序員,吃完飯還要自己收拾的那就是是C程序員。至于為什么會這樣,大家都明白(因為JAVA自帶垃圾回收機制,C需要
    的頭像 發(fā)表于 11-03 11:25 ?4320次閱讀

    優(yōu)秀程序員與糟糕程序員的變現(xiàn)差異

    軟件蠶食一切,未來屬于程序員。所以人人都想當程序員。但是并不是每個人都能當好程序員。在你做出決定前還是先看看自己能不能當好程序員吧。
    的頭像 發(fā)表于 11-07 16:14 ?3070次閱讀

    程序員最大的失敗是什么

    程序員最大的失敗就是認為自己是好的程序員。
    的頭像 發(fā)表于 11-18 16:26 ?3225次閱讀

    程序員的類型

    今天來聊個有趣的話題,你是什么類型的程序員? 在學校里或在公司里,你是不是接觸過不少其他的程序員,有沒有發(fā)現(xiàn),雖然同屬程序員科, 但也有眾多的不同。 今天我就來給程序員分個類,看看你是
    的頭像 發(fā)表于 11-28 16:39 ?4703次閱讀

    每個程序員都應該知道的內(nèi)存

    隨著CPU內(nèi)核變得更快和更多,大多數(shù)程序的限制因素是現(xiàn)在,也將是一段時間,內(nèi)存訪問。硬件設(shè)計師已經(jīng)想出了更復雜的內(nèi)存處理和加速技術(shù)(如CPU緩存),但是如果沒有程序員的幫助,這些功能就
    發(fā)表于 11-23 16:55 ?0次下載