最近在開發的程式。本來我是一直很喜歡的記憶體管理的,不需要擔心配置設定記憶體,隻管配置設定,垃圾收集器自己會給你回收記憶體的。現在開發的程式資料量很大,為了速度快,我準備把所有的資訊加載進記憶體,這樣可以保證快速響應。我還在反複算記憶體,想想自己的資料量,現在剛開始的時候應該夠了(我的機器是4g記憶體,雖然就認3.5g,但是比起我現在的資料量應該沒問題)。
沒想到第一個實驗的程式,跑了幾個小時,就遇到了out of memory exception了。看看自己的虛拟機設定,我設定的是-xms512m
-xmx1024m。想都沒想,直接改成-xms512m -xmx2048m,結果直接就could not reserve enough space for
object heap。程式都起不來了。這才發現原來最大記憶體還有限制。上網搜了一下,發現很多讨論這個問題的文章。最終在bea的dev2dev論壇發現了最有用的
一篇
這裡的版主yulimin 做了,得出結論:
公司
jvm版本
最大記憶體(兆)client 最大記憶體(兆)server
sun
1.5.x
1492
1520
1.5.5(linux)
2634
2660
1.4.2
1564
1564
1.4.2(linux)
1900
1260
ibm
2047
n/a
bea jrockit 1.5 (u3)
1909
1902
我現在用的是jdk1.6. 0_05,了一下。在client狀态下最大是,我的jdk不認-server參數,測試不了server狀态。估計差不多。
1.6.0
1442
看樣子用java想用大記憶體也是不可能的了。而且一般的說法是記憶體太大了,垃圾收集的時間就會長。這也可以了解,一般是記憶體不夠用了才收集的,掃描2g記憶體比1g當然要慢多了,而且記憶體對象多了,估計關系是指數上升的。
下面附上yulimin的測試方法和測試記錄。
測試方法:在指令行下用 java -xmxxxxxm -version
指令來進行測試,然後逐漸的增大xxxx的值,如果執行正常就表示指定的記憶體大小可用,否則會列印錯誤資訊。
堆(heap)和非堆(non-heap)記憶體
按照官方的說法:“java
虛拟機具有一個堆,堆是運作時資料區域,所有類執行個體和數組的記憶體均從此處配置設定。堆是在 java
虛拟機啟動時建立的。”“在jvm中堆之外的記憶體稱為非堆記憶體(non-heap
memory)”。可以看出jvm主要管理兩種類型的記憶體:堆和非堆。簡單來說堆就是java代碼可及的記憶體,是留給開發人員使用的;非堆就是jvm留給
自己用的,是以方法區、jvm内部處理或優化所需的記憶體(如jit編譯後的代碼緩存)、每個類結構(如運作時常數池、字段和方法資料)以及方法和構造方法
的代碼都在非堆記憶體中。
堆記憶體配置設定
jvm初始配置設定的記憶體由-xms指定,預設是實體記憶體的1/64;jvm最大配置設定的記憶體由
-xmx指定,預設是實體記憶體的1/4。預設空餘堆記憶體小于40%時,jvm就會增大堆直到-xmx的最大限制;空餘堆記憶體大于70%時,jvm會減少堆
直到-xms的最小限制。是以伺服器一般設定-xms、-xmx相等以避免在每次gc 後調整堆的大小。
非堆記憶體配置設定
jvm使用-xx:permsize設定非堆記憶體初始值,預設是實體記憶體的1/64;由xx:maxpermsize設定最大非堆記憶體的大小,預設是實體記憶體的1/4。
jvm記憶體限制(最大值)
首先jvm記憶體限制于實際的最大實體記憶體(廢話!呵呵),假設實體記憶體無限
大的話,jvm記憶體的最大值跟作業系統有很大的關系。簡單的說就32位處理器雖然可控記憶體空間有4gb,但是具體的作業系統會給一個限制,這個限制一般是
2gb-3gb(一般來說windows系統下為1.5g-2g,linux系統下為2g-3g),而64bit以上的處理器就不會有限制了。
是以說設定vm參數導緻程式無法啟動主要有以下幾種原因:
1) 參數中-xms的值大于-xmx,或者-xx:permsize的值大于-xx:maxpermsize; 2) -xmx的值和-xx:maxpermsize的總和超過了jvm記憶體的最大限制,比如目前作業系統最大記憶體限制,或者實際的實體記憶體等等。說到實際實體 記憶體這裡需要說明一點的是,如果你的記憶體是1024mb,但實際系統中用到的并不可能是1024mb,因為有一部分被硬體占用了。