<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

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

          共 5501字,需瀏覽 12分鐘

           ·

          2020-09-10 02:05

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

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

          66套java從入門到精通實(shí)戰(zhà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ù)組存儲占用內(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ù)組存儲占用內(nèi)存總量為:"+memory2+"MB"); }}

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

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

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

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

          1)maxMemory()這個(gè)方法返回的是java虛擬機(jī)(這個(gè)進(jìn)程)能構(gòu)從操作系統(tǒng)那里挖到的最大的內(nèi)存,以字節(jié)為單位,如果在運(yùn)行java程序的時(shí) 候,沒有添加-Xmx參數(shù),那么就是64兆,也就是說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)那里挖過來的內(nèi)存大小,也就是java虛擬機(jī)這個(gè)進(jìn)程當(dāng)時(shí)所占用的所有 內(nèi)存。如果在運(yùn)行java的時(shí)候沒有添加-Xms參數(shù),那么,在java程序運(yùn)行的過程的,內(nèi)存總是慢慢的從操作系統(tǒng)那里挖的,基本上是用多少挖多少,直 挖到maxMemory()為止,所以totalMemory()是慢慢增大的。如果用了-Xms參數(shù),程序在啟動的時(shí)候就會無條件的從操作系統(tǒng)中挖- Xms后面定義的內(nèi)存數(shù),然后在這些內(nèi)存用的差不多的時(shí)候,再去挖。

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

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

          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ù)組存儲占用內(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ù)組存儲占用內(nèi)存總量為:"+memory2+"MB"); }}

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

          用一維數(shù)組存儲占用內(nèi)存總量為:10MB用二維數(shù)組存儲占用內(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ù)組存儲占用內(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ù)組存儲占用內(nèi)存總量為:" + memory2 + "MB"); long endTime2 = System.currentTimeMillis(); // 獲取結(jié)束時(shí)間 System.out.println("程序運(yùn)行時(shí)間:" + (endTime2 - startTime2) + "ms"); }
          }

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

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

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


          三、分析

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

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

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

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

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

          代碼段:用來存放從硬盤上讀取的源程序代碼。

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

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

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

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

          • 對象數(shù)組;

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

          1)一維數(shù)組

          int[] arr = new int[3];

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


          2)二維數(shù)組

          那么二維數(shù)組是如何存儲的呢?事實(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];

          對于多維數(shù)組來說,道理是一樣的;

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

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


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

          本文鏈接:

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




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

          ???

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



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


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

          手機(jī)掃一掃分享

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

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  自拍偷拍成人在线视频 | 亚洲中文字幕乱伦 | 爱搞搞爱搞搞爱搞搞 | 午夜理理伦电影A片无码蜜桃av | 超碰人人艹|