精品国产人成在线_亚洲高清无码在线观看_国产在线视频国产永久2021_国产AV综合第一页一个的一区免费影院黑人_最近中文字幕MV高清在线视频

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

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

3天內不再提示

程序員眼里的內存(中)

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

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


什么是內存

C/C++內存模型

**堆區與棧區的本質

**

**JavaPython等內存模型

**

**Java內存模型

**

**Jave中的堆區與棧區是如何實現的

**

Python內存模型

指針與引用

進程的內存模型

幻想大師-操作系統

總結


堆與棧的本質是什么

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

在數據結構與算法中,我們也有堆和棧的概念,但那里指的不是內存,而是兩種數據結構。

你可能會想,我們為什么要費盡心力的提出堆和棧這兩個概念呢?之所以需要區分兩種內存用法,根源在于: 內存是有限的

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

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

堆和棧是計算機科學中很優秀的設計思想,這種設計思想充分的體現了計算機如何合理且靈活的使用有限資源。

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

Java、Python等內存模型

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

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

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

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

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

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

Java內存模型

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

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

Java中的堆和棧是如何實現的

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

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

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

一般情況下,當JVM運行一個Java函數時需要在堆上創建出Java函數的棧幀,然后把這些棧幀放入棧中(這里的棧指的是具有先進后出性質的數據結構)。希望大家不要被這句話繞暈,這里出現了兩個“棧”,但是含義完全不同。

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

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

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

void RunJavaFunction(JVM* jvm, string javaFunction) {


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

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

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

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

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

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

Python內存模型

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

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

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

Python core:所有非PyObject的內存請求都在這里分配的。

所以你會發現,Python中所有的內存同樣是解釋器在自己的堆上分配的。

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

    關注

    19

    文章

    2958

    瀏覽量

    104548
  • 堆棧
    +關注

    關注

    0

    文章

    182

    瀏覽量

    19732
  • python
    +關注

    關注

    56

    文章

    4782

    瀏覽量

    84453
收藏 人收藏

    評論

    相關推薦

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

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

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

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

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

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

    程序員如何定義

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

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

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

    什么是程序員

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

    程序員的未來

    程序員出路在何方程序員 創業如果你是程序員,也想創業,看看我說的。
    的頭像 發表于 06-12 17:29 ?2927次閱讀

    為什么要成為高級程序員

    程序員到高級程序員的職業生涯要經歷以下幾個階段:初級程序員、中級程序員、最后是高級程序員
    的頭像 發表于 07-11 16:51 ?2413次閱讀

    普通程序員和高級程序員有哪些區別

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

    如何定義程序員

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

    JAVA程序員和C程序員有什么區別

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

    優秀程序員與糟糕程序員的變現差異

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

    程序員最大的失敗是什么

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

    程序員的類型

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

    每個程序員都應該知道的內存

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