1. <strong id="7actg"></strong>
    2. <table id="7actg"></table>

    3. <address id="7actg"></address>
      <address id="7actg"></address>
      1. <object id="7actg"><tt id="7actg"></tt></object>

        一維數(shù)組和二維數(shù)組存儲(chǔ)占用內(nèi)存大小問(wèn)題

        共 5501字,需瀏覽 12分鐘

         ·

        2020-09-10 02:05

        點(diǎn)擊上方藍(lán)色字體,選擇“標(biāo)星公眾號(hào)”

        優(yōu)質(zhì)文章,第一時(shí)間送達(dá)

        66套java從入門到精通實(shí)戰(zhàn)課程分享?

        問(wèn)題:在java中,一維數(shù)組和二維數(shù)組在數(shù)據(jù)量一樣的情況下,開辟的內(nèi)存大小是怎樣的?

        一、嘗試階段:

        1、代碼一:

        public class OneArrayMemory{  public static void main(String[] args){    int num1 = 1024*1024*2;    int[] arr1 = new int[num1];    for(int i = 0;i < arr1.length;i++){      arr1[i] = i;    }
        //獲得占用內(nèi)存總數(shù),并將單位轉(zhuǎn)換為MB long memory1 = Runtime.getRuntime().totalMemory()/1024/1024; System.out.println("用一維數(shù)組存儲(chǔ)占用內(nèi)存總量為:"+memory1+"MB");
        int nums2 = 1024*1024; int[][] arr2 = new int[nums2][2]; for(int i = 0;i < arr2.length;i++){ arr2[i][0] = i; arr2[i][1] = i; }
        //獲得占用內(nèi)存總數(shù),并將單位轉(zhuǎn)換為MB long memory2 = Runtime.getRuntime().totalMemory()/1024/1024; System.out.println("用二維數(shù)組存儲(chǔ)占用內(nèi)存總量為:"+memory2+"MB"); }}

        2、運(yùn)行結(jié)果:

        用一維數(shù)組存儲(chǔ)占用內(nèi)存總量為:123MB用二維數(shù)組存儲(chǔ)占用內(nèi)存總量為:123MB

        ?3、結(jié)果有悖于常識(shí),百思不得解。后來(lái)查閱了資料,發(fā)現(xiàn)了了問(wèn)題所在。下面補(bǔ)充幾個(gè)知識(shí)點(diǎn):

        ? ? ? 最近在網(wǎng)上看到一些人討論到j(luò)ava.lang.Runtime類中的freeMemory(),totalMemory(),maxMemory ()這幾個(gè)方法的一些問(wèn)題,很多人感到很疑惑,為什么,在java程序剛剛啟動(dòng)起來(lái)的時(shí)候freeMemory()這個(gè)方法返回的只有一兩兆字節(jié),而隨著 java程序往前運(yùn)行,創(chuàng)建了不少的對(duì)象,freeMemory()這個(gè)方法的返回有時(shí)候不但沒(méi)有減少,反而會(huì)增加。這些人對(duì)freeMemory()這 個(gè)方法的意義應(yīng)該有一些誤解,他們認(rèn)為這個(gè)方法返回的是操作系統(tǒng)的剩余可用內(nèi)存,其實(shí)根本就不是這樣的。這三個(gè)方法反映的都是java這個(gè)進(jìn)程的內(nèi)存情 況,跟操作系統(tǒng)的內(nèi)存根本沒(méi)有關(guān)系。下面結(jié)合totalMemory(),maxMemory()一起來(lái)解釋。

        1)maxMemory()這個(gè)方法返回的是java虛擬機(jī)(這個(gè)進(jìn)程)能構(gòu)從操作系統(tǒng)那里挖到的最大的內(nèi)存,以字節(jié)為單位,如果在運(yùn)行java程序的時(shí) 候,沒(méi)有添加-Xmx參數(shù),那么就是64兆,也就是說(shuō)maxMemory()返回的大約是64*1024*1024字節(jié),這是java虛擬機(jī)默認(rèn)情況下能 從操作系統(tǒng)那里挖到的最大的內(nèi)存。如果添加了-Xmx參數(shù),將以這個(gè)參數(shù)后面的值為準(zhǔn),例如java -cp ClassPath -Xmx512m ClassName,那么最大內(nèi)存就是512*1024*0124字節(jié)。

        2)totalMemory()這個(gè)方法返回的是java虛擬機(jī)現(xiàn)在已經(jīng)從操作系統(tǒng)那里挖過(guò)來(lái)的內(nèi)存大小,也就是java虛擬機(jī)這個(gè)進(jìn)程當(dāng)時(shí)所占用的所有 內(nèi)存。如果在運(yùn)行java的時(shí)候沒(méi)有添加-Xms參數(shù),那么,在java程序運(yùn)行的過(guò)程的,內(nèi)存總是慢慢的從操作系統(tǒng)那里挖的,基本上是用多少挖多少,直 挖到maxMemory()為止,所以totalMemory()是慢慢增大的。如果用了-Xms參數(shù),程序在啟動(dòng)的時(shí)候就會(huì)無(wú)條件的從操作系統(tǒng)中挖- Xms后面定義的內(nèi)存數(shù),然后在這些內(nèi)存用的差不多的時(shí)候,再去挖。

        3)freeMemory()是什么呢,剛才講到如果在運(yùn)行java的時(shí)候沒(méi)有添加-Xms參數(shù),那么,在java程序運(yùn)行的過(guò)程的,內(nèi)存總是慢慢的從操 作系統(tǒng)那里挖的,基本上是用多少挖多少,但是java虛擬機(jī)100%的情況下是會(huì)稍微多挖一點(diǎn)的,這些挖過(guò)來(lái)而又沒(méi)有用上的內(nèi)存,實(shí)際上就是 freeMemory(),所以freeMemory()的值一般情況下都是很小的,但是如果你在運(yùn)行java程序的時(shí)候使用了-Xms,這個(gè)時(shí)候因?yàn)槌?序在啟動(dòng)的時(shí)候就會(huì)無(wú)條件的從操作系統(tǒng)中挖-Xms后面定義的內(nèi)存數(shù),這個(gè)時(shí)候,挖過(guò)來(lái)的內(nèi)存可能大部分沒(méi)用上,所以這個(gè)時(shí)候freeMemory()可 能會(huì)有些大。

        結(jié)果異常的根源:totalMemory() 減去freeMemory()才是真正給數(shù)組開辟的內(nèi)存大?。。?!

        4、修改代碼

        public class OneArrayMemory{  public static void main(String[] args){    int num1 = 1024*1024*2;    int[] arr1 = new int[num1];    for(int i = 0;i < arr1.length;i++){      arr1[i] = i;    }
        //獲得占用內(nèi)存總數(shù),并將單位轉(zhuǎn)換為MB long memory1 = Runtime.getRuntime().totalMemory()/1024/1024 - Runtime.getRuntime().freeMemory() / 1024 / 1024; //long memory1 = Runtime.getRuntime().totalMemory()/1024/1024; System.out.println("用一維數(shù)組存儲(chǔ)占用內(nèi)存總量為:"+memory1+"MB");
        int nums2 = 1024*1024; int[][] arr2 = new int[nums2][2]; for(int i = 0;i < arr2.length;i++){ arr2[i][0] = i; arr2[i][1] = i; }
        //獲得占用內(nèi)存總數(shù),并將單位轉(zhuǎn)換為MB long memory2 = Runtime.getRuntime().totalMemory()/1024/1024 - Runtime.getRuntime().freeMemory() / 1024 / 1024; //long memory2 = Runtime.getRuntime().totalMemory()/1024/1024; System.out.println("用二維數(shù)組存儲(chǔ)占用內(nèi)存總量為:"+memory2+"MB"); }}

        第二次運(yùn)行結(jié)果:?

        用一維數(shù)組存儲(chǔ)占用內(nèi)存總量為:10MB用二維數(shù)組存儲(chǔ)占用內(nèi)存總量為:37MB

        5、代碼三:

        import java.util.Arrays;  public class OneArrayMemory {    public static void main(String[] args) {        long startTime1 = System.currentTimeMillis(); // 獲取開始時(shí)間        int num1 = 1024 * 1024 * 2;        int[] arr1 = new int[num1];        Arrays.fill(arr1, 1);
        // 獲得占用內(nèi)存總數(shù),并將單位轉(zhuǎn)換成MB long memory1 = Runtime.getRuntime().totalMemory() / 1024 / 1024 - Runtime.getRuntime().freeMemory() / 1024 / 1024; System.out.println("用一維數(shù)組存儲(chǔ)占用內(nèi)存總量為:" + memory1 + "MB"); long endTime1 = System.currentTimeMillis(); // 獲取結(jié)束時(shí)間 System.out.println("程序運(yùn)行時(shí)間:" + (endTime1 - startTime1) + "ms");
        long startTime2 = System.currentTimeMillis(); // 獲取開始時(shí)間 int num2 = 1024 * 1024; int[][] arr2 = new int[num2][2]; for (int[] i : arr2) { Arrays.fill(i, 1); }
        // 獲得占用內(nèi)存總數(shù),并將單位轉(zhuǎn)換成MB long memory2 = Runtime.getRuntime().totalMemory() / 1024 / 1024 - Runtime.getRuntime().freeMemory() / 1024 / 1024; System.out.println("用二維數(shù)組存儲(chǔ)占用內(nèi)存總量為:" + memory2 + "MB"); long endTime2 = System.currentTimeMillis(); // 獲取結(jié)束時(shí)間 System.out.println("程序運(yùn)行時(shí)間:" + (endTime2 - startTime2) + "ms"); }
        }

        運(yùn)行結(jié)果:

        用一維數(shù)組存儲(chǔ)占用內(nèi)存總量為:10MB程序運(yùn)行時(shí)間:12ms用二維數(shù)組存儲(chǔ)占用內(nèi)存總量為:38MB程序運(yùn)行時(shí)間:115ms

        二、結(jié)論:數(shù)據(jù)量相同的情況下,二維數(shù)組比一維數(shù)組需要開辟更大的內(nèi)存空間。


        三、分析

        1、一個(gè)完整的Java程序運(yùn)行過(guò)程會(huì)涉及以下內(nèi)存區(qū)域:

        寄存器:JVM內(nèi)部虛擬寄存器,存取速度非常快,程序不可控制。

        :保存局部變量的值,包括:1.用來(lái)保存基本數(shù)據(jù)類型的值;2.保存類的實(shí)例,即堆區(qū)對(duì)象的引用(指針)。也可以用來(lái)保存加載方法時(shí)的幀。

        :用來(lái)存放動(dòng)態(tài)產(chǎn)生的數(shù)據(jù),比如new出來(lái)的對(duì)象。注意創(chuàng)建出來(lái)的對(duì)象只包含屬于各自的成員變量,并不包括成員方法。因?yàn)橥粋€(gè)類的對(duì)象擁有各自的成員變量,存儲(chǔ)在各自的堆中,但是他們共享該類的方法,并不是每創(chuàng)建一個(gè)對(duì)象就把成員方法復(fù)制一次。

        常量池:JVM為每個(gè)已加載的類型維護(hù)一個(gè)常量池,常量池就是這個(gè)類型用到的常量的一個(gè)有序集合。包括直接常量(基本類型,String)和對(duì)其他類型、方法、字段的符號(hào)引用(1)。池中的數(shù)據(jù)和數(shù)組一樣通過(guò)索引訪問(wèn)。由于常量池包含了一個(gè)類型所有的對(duì)其他類型、方法、字段的符號(hào)引用,所以常量池在Java的動(dòng)態(tài)鏈接中起了核心作用。常量池存在于堆中。

        代碼段:用來(lái)存放從硬盤上讀取的源程序代碼。

        數(shù)據(jù)段:用來(lái)存放static定義的靜態(tài)成員。

        ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??

        Java中有兩種類型的數(shù)組:

        • 基本數(shù)據(jù)類型數(shù)組;

        • 對(duì)象數(shù)組;

        2、當(dāng)一個(gè)對(duì)象使用關(guān)鍵字“new”創(chuàng)建時(shí),會(huì)在堆上分配內(nèi)存空間,然后返回對(duì)象的引用,這對(duì)數(shù)組來(lái)說(shuō)也是一樣的,因?yàn)閿?shù)組也是一個(gè)對(duì)象;

        1)一維數(shù)組

        int[] arr = new int[3];

        在以上代碼中,arr變量存放了數(shù)組對(duì)象的引用;如果你創(chuàng)建了空間大小為10的整形數(shù)組,情況是一樣的,一個(gè)數(shù)組對(duì)象所占的空間在堆上被分配,然后返回其引用;


        2)二維數(shù)組

        那么二維數(shù)組是如何存儲(chǔ)的呢?事實(shí)上,在Java中只有一維數(shù)組,二維數(shù)組是一個(gè)存放了數(shù)組的數(shù)組,如下代碼及示意圖:

        int[][] arr = new int[3][];arr[0] = new int[3];arr[1] = new int[5];arr[2] = new int[4];

        對(duì)于多維數(shù)組來(lái)說(shuō),道理是一樣的;

        由此可見,數(shù)據(jù)量相同的情況下,開辟多維數(shù)組會(huì)產(chǎn)生更大的開銷。

        3)趣事:對(duì)于java二維數(shù)組建議 Int[][] arr=new Int[2][100] 而不要使用int[][] arr=new int[100][2],因?yàn)楹笳邥?huì)產(chǎn)生更多的開銷。


        版權(quán)聲明:本文為博主原創(chuàng)文章,遵循?CC 4.0 BY-SA?版權(quán)協(xié)議,轉(zhuǎn)載請(qǐng)附上原文出處鏈接和本聲明。

        本文鏈接:

        https://blog.csdn.net/weixin_40449300/article/details/83832947




        粉絲福利:108本java從入門到大神精選電子書領(lǐng)取

        ???

        ?長(zhǎng)按上方鋒哥微信二維碼?2 秒
        備注「1234」即可獲取資料以及
        可以進(jìn)入java1234官方微信群



        感謝點(diǎn)贊支持下哈?


        瀏覽 54
        點(diǎn)贊
        評(píng)論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報(bào)
        評(píng)論
        圖片
        表情
        推薦
        點(diǎn)贊
        評(píng)論
        收藏
        分享

        手機(jī)掃一掃分享

        分享
        舉報(bào)
        1. <strong id="7actg"></strong>
        2. <table id="7actg"></table>

        3. <address id="7actg"></address>
          <address id="7actg"></address>
          1. <object id="7actg"><tt id="7actg"></tt></object>
            成人做爰黄AAA片爽爽视频美国 | 公交车她被揉的开始呻吟起来视频 | TS国产人妖视频在线观看 | 国产夫妻精品自拍 | 老师让我她我爽了好久视频 | 性爱福利视频 | 强开乳罩摸双乳吃奶小说 | 草逼视频链接 | 亚洲精品操逼 | 美女被操视频在线看 |