wasjava虛擬機內存
Ⅰ java虛擬機內存分配與回收機制
[轉帖] Java 中的堆和棧
簡單的說:
Java把內存劃分成兩種:一種是棧內存,一種是堆內存。
在函數中定義的一些基本類型的變數和對象的引用變數都在函數的棧內存中分配。
當在一段代碼塊定義一個變數時,Java就在棧中為這個變數分配內存空間,當超過變數的作用域後,Java會自動釋放掉為該變數所分配的內存空間,該內存空間可以立即被另作他用。
堆內存用來存放由new創建的對象和數組。
在堆中分配的內存,由Java虛擬機的自動垃圾回收器來管理。
在堆中產生了一個數組或對象後,還可以在棧中定義一個特殊的變數,讓棧中這個變數的取值等於數組或對象在堆內存中的首地址,棧中的這個變數就成了數組或對象的引用變數。
引用變數就相當於是為數組或對象起的一個名稱,以後就可以在程序中使用棧中的引用變數來訪問堆中的數組或對象。
具體的說:
棧與堆都是Java用來在Ram中存放數據的地方。與C++不同,Java自動管理棧和堆,程序員不能直接地設置棧或堆。
Java的堆是一個運行時數據區,類的(對象從中分配空間。這些對象通過new、newarray、anewarray和multianewarray等 指令建立,它們不需要程序代碼來顯式的釋放。堆是由垃圾回收來負責的,堆的優勢是可以動態地分配內存大小,生存期也不必事先告訴編譯器,因為它是在運行時 動態分配內存的,Java的垃圾收集器會自動收走這些不再使用的數據。但缺點是,由於要在運行時動態分配內存,存取速度較慢。
棧的優勢是,存取速度比堆要快,僅次於寄存器,棧數據可以共享。但缺點是,存在棧中的數據大小與生存期必須是確定的,缺乏靈活性。棧中主要存放一些基本 類型的變數(,int, short, long, byte, float, double, boolean, char)和對象句柄。
棧有一個很重要的特殊性,就是存在棧中的數據可以共享。假設我們同時定義:
int a = 3;
int b = 3;
編譯器先處理int a = 3;首先它會在棧中創建一個變數為a的引用,然後查找棧中是否有3這個值,如果沒找到,就將3存放進來,然後將a指向3。接著處理int b = 3;在創建完b的引用變數後,因為在棧中已經有3這個值,便將b直接指向3。這樣,就出現了a與b同時均指向3的情況。這時,如果再令a=4;那麼編譯器 會重新搜索棧中是否有4值,如果沒有,則將4存放進來,並令a指向4;如果已經有了,則直接將a指向這個地址。因此a值的改變不會影響到b的值。要注意這 種數據的共享與兩個對象的引用同時指向一個對象的這種共享是不同的,因為這種情況a的修改並不會影響到b, 它是由編譯器完成的,它有利於節省空間。而一個對象引用變數修改了這個對象的內部狀態,會影響到另一個對象引用變數。
String是一個特殊的包裝類數據。可以用:
String str = new String("abc");
String str = "abc";
兩種的形式來創建,第一種是用new()來新建對象的,它會在存放於堆中。每調用一次就會創建一個新的對象。
而第二種是先在棧中創建一個對String類的對象引用變數str,然後查找棧中有沒有存放"abc",如果沒有,則將"abc"存放進棧,並令str指向」abc」,如果已經有」abc」 則直接令str指向「abc」。
比較類裡面的數值是否相等時,用equals()方法;當測試兩個包裝類的引用是否指向同一個對象時,用==,下面用例子說明上面的理論。
String str1 = "abc";
String str2 = "abc";
System.out.println(str1==str2); //true
可以看出str1和str2是指向同一個對象的。
String str1 =new String ("abc");
String str2 =new String ("abc");
System.out.println(str1==str2); // false
用new的方式是生成不同的對象。每一次生成一個。
因此用第二種方式創建多個」abc」字元串,在內存中其實只存在一個對象而已. 這種寫法有利與節省內存空間. 同時它可以在一定程度上提高程序的運行速度,因為JVM會自動根據棧中數據的實際情況來決定是否有必要創建新對象。而對於String str = new String("abc");的代碼,則一概在堆中創建新對象,而不管其字元串值是否相等,是否有必要創建新對象,從而加重了程序的負擔。
另一方面, 要注意: 我們在使用諸如String str = "abc";的格式定義類時,總是想當然地認為,創建了String類的對象str。擔心陷阱!對象可能並沒有被創建!而可能只是指向一個先前已經創建的 對象。只有通過new()方法才能保證每次都創建一個新的對象。 由於String類的immutable性質,當String變數需要經常變換其值時,應該考慮使用StringBuffer類,以提高程序效率。
java中內存分配策略及堆和棧的比較
2.1 內存分配策略
按照編譯原理的觀點,程序運行時的內存分配有三種策略,分別是靜態的,棧式的,和堆式的.
靜態存儲分配是指在編譯時就能確定每個數據目標在運行時刻的存儲空間需求,因而在編譯時就可以給他們分配固定的內存空間.這種分配策略要求程序代碼中不允 許有可變數據結構(比如可變數組)的存在,也不允許有嵌套或者遞歸的結構出現,因為它們都會導致編譯程序無法計算準確的存儲空間需求.
棧式存儲分配也可稱為動態存儲分配,是由一個類似於堆棧的運行棧來實現的.和靜態存儲分配相反,在棧式存儲方案中,程序對數據區的需求在編譯時是完全未知 的,只有到運行的時候才能夠知道,但是規定在運行中進入一個程序模塊時,必須知道該程序模塊所需的數據區大小才能夠為其分配內存.和我們在數據結構所熟知 的棧一樣,棧式存儲分配按照先進後出的原則進行分配。
靜態存儲分配要求在編譯時能知道所有變數的存儲要求,棧式存儲分配要求在過程的入口處必須知道所有的存儲要求,而堆式存儲分配則專門負責在編譯時或運行時 模塊入口處都無法確定存儲要求的數據結構的內存分配,比如可變長度串和對象實例.堆由大片的可利用塊或空閑塊組成,堆中的內存可以按照任意順序分配和釋 放.
2.2 堆和棧的比較
上面的定義從編譯原理的教材中總結而來,除靜態存儲分配之外,都顯得很呆板和難以理解,下面撇開靜態存儲分配,集中比較堆和棧:
從堆和棧的功能和作用來通俗的比較,堆主要用來存放對象的,棧主要是用來執行程序的.而這種不同又主要是由於堆和棧的特點決定的:
在編程中,例如C/C++中,所有的方法調用都是通過棧來進行的,所有的局部變數,形式參數都是從棧中分配內存空間的。實際上也不是什麼分配,只是從棧頂 向上用就行,就好像工廠中的傳送帶(conveyor belt)一樣,Stack Pointer會自動指引你到放東西的位置,你所要做的只是把東西放下來就行.退出函數的時候,修改棧指針就可以把棧中的內容銷毀.這樣的模式速度最快, 當然要用來運行程序了.需要注意的是,在分配的時候,比如為一個即將要調用的程序模塊分配數據區時,應事先知道這個數據區的大小,也就說是雖然分配是在程 序運行時進行的,但是分配的大小多少是確定的,不變的,而這個"大小多少"是在編譯時確定的,不是在運行時.
堆是應用程序在運行的時候請求操作系統分配給自己內存,由於從操作系統管理的內存分配,所以在分配和銷毀時都要佔用時間,因此用堆的效率非常低.但是堆的 優點在於,編譯器不必知道要從堆里分配多少存儲空間,也不必知道存儲的數據要在堆里停留多長的時間,因此,用堆保存數據時會得到更大的靈活性。事實上,面 向對象的多態性,堆內存分配是必不可少的,因為多態變數所需的存儲空間只有在運行時創建了對象之後才能確定.在C++中,要求創建一個對象時,只需用 new命令編制相關的代碼即可。執行這些代碼時,會在堆里自動進行數據的保存.當然,為達到這種靈活性,必然會付出一定的代價:在堆里分配存儲空間時會花 掉更長的時間!這也正是導致我們剛才所說的效率低的原因,看來列寧同志說的好,人的優點往往也是人的缺點,人的缺點往往也是人的優點(暈~).
2.3 JVM中的堆和棧
JVM是基於堆棧的虛擬機.JVM為每個新創建的線程都分配一個堆棧.也就是說,對於一個Java程序來說,它的運行就是通過對堆棧的操作來完成的。堆棧以幀為單位保存線程的狀態。JVM對堆棧只進行兩種操作:以幀為單位的壓棧和出棧操作。
我們知道,某個線程正在執行的方法稱為此線程的當前方法.我們可能不知道,當前方法使用的幀稱為當前幀。當線程激活一個Java方法,JVM就會在線程的 Java堆棧里新壓入一個幀。這個幀自然成為了當前幀.在此方法執行期間,這個幀將用來保存參數,局部變數,中間計算過程和其他數據.這個幀在這里和編譯 原理中的活動紀錄的概念是差不多的.
從Java的這種分配機制來看,堆棧又可以這樣理解:堆棧(Stack)是操作系統在建立某個進程時或者線程(在支持多線程的操作系統中是線程)為這個線程建立的存儲區域,該區域具有先進後出的特性。
每一個Java應用都唯一對應一個JVM實例,每一個實例唯一對應一個堆。應用程序在運行中所創建的所有類實例或數組都放在這個堆中,並由應用所有的線程 共享.跟C/C++不同,Java中分配堆內存是自動初始化的。Java中所有對象的存儲空間都是在堆中分配的,但是這個對象的引用卻是在堆棧中分配,也 就是說在建立一個對象時從兩個地方都分配內存,在堆中分配的內存實際建立這個對象,而在堆棧中分配的內存只是一個指向這個堆對象的指針(引用)而已。
轉自:http://www.anyuok.cn/showbbs.asp?bd=22&id=142&totable=1
呵呵,在看到你的問題前10分鍾才看的這個文章...
Ⅱ 如何修改java虛擬機內存
1、普通java應用程序,使用java命令運行,
java -Xms1024m -Xmx1024m -XX:MaxNewSize=256m -XX:MaxPermSize=256m -jar
2、tomcat
在catalina.bat的set JAVA_OPTS修改為set JAVA_OPTS=-Xms1024m -Xmx1024m -XX:MaxNewSize=256m -XX:MaxPermSize=256m –server
3、eclipse中運行應用程序
程序右鍵選屬性->run/debug settings->選中應用程序->編輯->Arguments->VM arguments輸入框輸入
-Xms1024m -Xmx1024m -XX:MaxNewSize=256m -XX:MaxPermSize=256m
4、weblogic
在$DOMAIN_HOME/bin/setDomainEnv.sh修改內存
Ⅲ java 虛擬機內存怎麼設置最好
參數有四個:
-Xmx
Java
Heap最大值,默認值為
物理內存
的1/4,最佳設值應該視物理內存大小及計算機內其他內存開銷而定;
-Xms
Java
Heap初始值,Server端JVM最好將-Xms和-Xmx設為相同值,開發測試機JVM可以保留默認值;
-Xmn
Java
Heap
Young區大小,不熟悉最好保留默認值;
-Xss
每個線程的Stack大小,不熟悉最好保留默認值;
Ⅳ 如何設置Java虛擬機JVM啟動內存參數
Tomcat默認的Java虛擬機JVM啟動內存參數大約只有64MB或者128MB,非常小,遠遠沒有利用現在伺服器的強大內存,所以要設置Java虛擬機JVM啟動內存參數。具體設置方法為:
Tomcat修改TOMCAT_HOME/bin/catalina.bat,在[echo Using CATALINA_BASE:
"%CATALINA_BASE%"] 上面加入,比如:
set JAVA_OPTS= -server -Xms1536m -Xmx1536m或者JAVA_OPTS="-server -Xms1536m
-Xmx1536m",
伺服器模式參數-server不加也可以 ,就變成
set JAVA_OPTS= -Xms1536m -Xmx1536m或者JAVA_OPTS=" -Xms1536m -Xmx1536m",
1536m只是舉個例子,具體可以在DOS命令窗口中測試能使用多大的Java虛擬機內存,能顯示JDK/JRE/JVM版本號的就說明能使用命令中設置的Java虛擬機內存,如執行
Java -Xmx1280m -version;
Java -Xmx1408m -version;
Java -Xmx1536m -version;
Java -Xmx1664m -version;
Java -Xmx2048m -version;
比如在下列DOS命令窗口中執行java -Xmx1024m
-version,顯示出JDK/JRE/JVM版本號,說明最大能使用1024MB的Java虛擬機內存:
等等,但是JVM啟動內存參數也不可能無限增大,因為他受限於物理內存和操作系統的限制,Windows操作系統下一般可以使用1.6GB左右的Java虛擬機內存,有些JDK如Jrockit可能最大可達1.9GB左右,此外,Linux、小型機AIX等情況可以較大。
Ⅳ 怎樣修改java虛擬機的內存大小
修改java虛擬機的內存大小:
Window--Preferences如圖下所示
Ⅵ 如何調整java虛擬機內存大小
在一些規模稍大的應用中,Java虛擬機(JVM)的內存設置尤為重要,想在項目中取得好的效率,GC(垃圾回收)的設置是第一步。
PermGen space:全稱是Permanent Generation space.就是說是永久保存的區域,用於存放Class和Meta信息,Class在被Load的時候被放入該區域Heap space:存放Instance。
GC(Garbage Collection)應該不會對PermGen space進行清理,所以如果你的APP會LOAD很多CLASS的話,就很可能出現PermGen space錯誤
Java Heap分為3個區
1.Young
2.Old
3.Permanent
Young保存剛實例化的對象。當該區被填滿時,GC會將對象移到Old區。Permanent區則負責保存反射對象,本文不討論該區。
JVM的Heap分配可以使用-X參數設定,
-Xms
初始Heap大小
-Xmx
java heap最大值
-Xmn
young generation的heap大小
JVM有2個GC線程
第一個線程負責回收Heap的Young區
第二個線程在Heap不足時,遍歷Heap,將Young 區升級為Older區
Older區的大小等於-Xmx減去-Xmn,不能將-Xms的值設的過大,因為第二個線程被迫運行會降低JVM的性能。
為什麼一些程序頻繁發生GC?
有如下原因:
1.程序內調用了System.gc()或Runtime.gc()。
2.一些中間件軟體調用自己的GC方法,此時需要設置參數禁止這些GC。
3.Java的Heap太小,一般默認的Heap值都很小。
4.頻繁實例化對象,Release對象 此時盡量保存並重用對象,例如使用StringBuffer()和String()。
如果你發現每次GC後,Heap的剩餘空間會是總空間的50%,這表示你的Heap處於健康狀態,許多Server端的Java程序每次GC後最好能有65%的剩餘空間
經驗之談:
1.Server端JVM最好將-Xms和-Xmx設為相同值。為了優化GC,最好讓-Xmn值約等於-Xmx的1/3。
2.一個GUI程序最好是每10到20秒間運行一次GC,每次在半秒之內完成。
注意:
1.增加Heap的大小雖然會降低GC的頻率,但也增加了每次GC的時間。並且GC運行時,所有的用戶線程將暫停,也就是GC期間,Java應用程序不做任何工作。
2.Heap大小並不決定進程的內存使用量。進程的內存使用量要大於-Xmx定義的值,因為Java為其他任務分配內存,例如每個線程的Stack等。
Stack的設定
每個線程都有他自己的Stack。
-Xss
每個線程的Stack大小
Stack的大小限制著線程的數量。如果Stack過大就好導致內存溢漏。-Xss參數決定Stack大小,例如-Xss1024K。如果Stack太小,也會導致Stack溢漏。
硬體環境
硬體環境也影響GC的效率,例如機器的種類,內存,swap空間,和CPU的數量。
如果你的程序需要頻繁創建很多transient對象,會導致JVM頻繁GC。這種情況你可以增加機器的內存,來減少Swap空間的使用。
4種GC
1、第一種為單線程GC,也是默認的GC,該GC適用於單CPU機器。
2、第二種為Throughput GC,是多線程的GC,適用於多CPU,使用大量線程的程序。第二種GC與第一種GC相似,不同在於GC在收集Young區是多線程的,但在Old區和第一種一樣,仍然採用單線程。-XX:+UseParallelGC參數啟動該GC。
3、第三種為Concurrent Low Pause GC,類似於第一種,適用於多CPU,並要求縮短因GC造成程序停滯的時間。這種GC可以在Old區的回收同時,運行應用程序。-XX:+UseConcMarkSweepGC參數啟動該GC。
4、第四種為Incremental Low Pause GC,適用於要求縮短因GC造成程序停滯的時間。這種GC可以在Young區回收的同時,回收一部分Old區對象。-Xincgc參數啟動該GC。
單文件的JVM內存進行設置
默認的java虛擬機的大小比較小,在對大數據進行處理時java就會報錯:java.lang.OutOfMemoryError。
設置jvm內存的方法,對於單獨的.class,可以用下面的方法對Test運行時的jvm內存進行設置。
java -Xms64m -Xmx256m Test
-Xms是設置內存初始化的大小
-Xmx是設置最大能夠使用內存的大小(最好不要超過物理內存大小)
tomcat啟動jvm內存設置
Linux:
在/usr/local/apache-tomcat-5.5.23/bin目錄下的catalina.sh添加:JAVA_OPTS='-Xms512m -Xmx1024m'要加「m」說明是MB,否則就是KB了,在啟動tomcat時會報內存不足。
-Xms:初始值
-Xmx:最大值
-Xmn:最小值Windows
在catalina.bat最前面加入
set JAVA_OPTS=-Xms128m -Xmx350m 如果用startup.bat啟動tomcat,OK設置生效.夠成功的分配200M內存.但是如果不是執行startup.bat啟動tomcat而是利用windows的系統服務啟動tomcat服務,上面的設置就不生效了,就是說set JAVA_OPTS=-Xms128m -Xmx350m 沒起作用.上面分配200M內存就OOM了..windows服務執行的是bin\tomcat.exe.他讀取注冊表中的值,而不是catalina.bat的設置.解決辦法:
修改注冊表HKEY_LOCAL_MACHINE\SOFTWARE\Apache Software Foundation\Tomcat Service Manager\Tomcat5\Parameters\JavaOptions
原值為
-Dcatalina.home="C:\ApacheGroup\Tomcat 5.0"
-Djava.endorsed.dirs="C:\ApacheGroup\Tomcat 5.0\common\endorsed"
-Xrs加入 -Xms300m -Xmx350m
重起tomcat服務,設置生效
weblogic啟動jvm內存設置
在weblogic中,可以在startweblogic.cmd中對每個domain虛擬內存的大小進行設置,默認的設置是在commEnv.cmd裡面。
JBoss
默認可以使用的內存為64MB
$JBOSSDIR$/bin/run.config
JAVA_OPTS = "-server -Xms128 -Xmx512"
Eclipse
在所在目錄下,鍵入
eclipse.exe -vmargs -Xms256m -Xmx512m
256m表示JVM堆內存最小值
512m表示JVM堆內存最大
Websphere
進入控制台去設置:應用程序伺服器 > server1 > 進程定義 > Java 虛擬機
Ⅶ JAVA虛擬機內存
我認為是3~4M,因為系統本身要佔用一定內存,一般的程序都沒有問題,問題你可能同打開多個程序,那就要看他們累積佔用多少內存了。最好不要達到4~5M,因為程序運行中可能會增加內存開銷,如果太大有可能造成程序崩潰。
Ⅷ 如何修改java虛擬機內存
一、設置JVM內存設置
1. 設置JVM內存的參數有四個:
-Xmx Java Heap最大值,默認值為物理內存的1/4,最佳設值應該視物理內存大小及計算機內其他內存開銷而定;
-Xms Java Heap初始值,Server端JVM最好將-Xms和-Xmx設為相同值,開發測試機JVM可以保留默認值;
-Xmn Java Heap Young區大小,不熟悉最好保留默認值;
-Xss 每個線程的Stack大小,不熟悉最好保留默認值;
2. 如何設置JVM內存分配:
(1)當在命令提示符下啟動並使用JVM時(只對當前運行的類Test生效):
java -Xmx128m -Xms64m -Xmn32m -Xss16m Test
(2)當在集成開發環境下(如eclipse)啟動並使用JVM時:
a. 在eclipse根目錄下打開eclipse.ini,默認內容為(這里設置的是運行當前開發工具的JVM內存分配):
-vmargs
-Xms40m
-Xmx256m
-vmargs表示以下為虛擬機設置參數,可修改其中的參數值,也可添加-Xmn,-Xss,另外,eclipse.ini內還可以設置非堆內存,如:-XX:PermSize=56m,-XX:MaxPermSize=128m。
此處設置的參數值可以通過以下配置在開發工具的狀態欄顯示:
在eclipse根目錄下創建文件options,文件內容為:org.eclipse.ui/perf/showHeapStatus=true
修改eclipse根目錄下的eclipse.ini文件,在開頭處添加如下內容:
-debug
options
-vm
javaw.exe
重新啟動eclipse,就可以看到下方狀態條多了JVM信息。
b. 打開eclipse-窗口-首選項-Java-已安裝的JRE(對在當前開發環境中運行的java程序皆生效)
編輯當前使用的JRE,在預設VM參數中輸入:-Xmx128m -Xms64m -Xmn32m -Xss16m
c. 打開eclipse-運行-運行-Java應用程序(只對所設置的java類生效)
選定需設置內存分配的類-自變數,在VM自變數中輸入:-Xmx128m -Xms64m -Xmn32m -Xss16m
註:如果在同一開發環境中同時進行了b和c設置,則b設置生效,c設置無效,如:
開發環境的設置為:-Xmx256m,而類Test的設置為:-Xmx128m -Xms64m,則運行Test時生效的設置為:
-Xmx256m -Xms64m
(3)當在伺服器環境下(如Tomcat)啟動並使用JVM時(對當前伺服器環境下所以Java程序生效):
a. 設置環境變數:
變數名:CATALINA_OPTS
變數值:-Xmx128m -Xms64m -Xmn32m -Xss16m
b. 打開Tomcat根目錄下的bin文件夾,編輯catalina.bat,將其中的�TALINA_OPTS%(共有四處)替換為:-Xmx128m -Xms64m -Xmn32m -Xss16m