轉一篇關於內存模型很好的文章【http://ifeve.com/under-the-hood-runtime-data-areas-javas-memory-model/】html
原文連接java
全部的Java開發人員可能會遇到這樣的困惑?我該爲堆內存設置多大空間呢?OutOfMemoryError的異常到底涉及到運行時數據的哪塊區域?該怎麼解決呢?linux
Java內存模型在JVM specification, Java SE 7 Edition, and mainly in the chapters 「2.5 Runtime Data Areas」 and 「2.6 Frames」中有詳細的說明。對象和類的數據存儲在3個不一樣的內存區域:堆(heap space)、方法區(method area)、本地區(native area)。web
堆內存存放對象以及數組的數據,方法區存放類的信息(包括類名、方法、字段)、靜態變量、編譯器編譯後的代碼,本地區包含線程棧、本地方法棧等存放線程apache
方法區有時被稱爲持久代(PermGen)。數組
全部的對象在實例化後的整個運行週期內,都被存放在堆內存中。堆內存又被劃分紅不一樣的部分:伊甸區(Eden),倖存者區域(Survivor Sapce),老年代(Old Generation Space)。oracle
方法的執行都是伴隨着線程的。原始類型的本地變量以及引用都存放在線程棧中。而引用關聯的對象好比String,都存在在堆中。爲了更好的理解上面這段話,咱們能夠看一個例子:jvm
01 |
import java.text.SimpleDateFormat; |
02 |
import java.util.Date; |
03 |
04 |
import org.apache.log4j.Logger; |
05 |
06 |
public class HelloWorld { |
07 |
private static Logger LOGGER = Logger.getLogger(HelloWorld. class .getName()); |
08 |
09 |
public void sayHello(String message) { |
10 |
SimpleDateFormat formatter = new SimpleDateFormat( "dd.MM.YYYY" ); |
11 |
String today = formatter.format( new Date()); |
12 |
LOGGER.info(today + ": " + message); |
13 |
} |
14 |
} |
這段程序的數據在內存中的存放以下:jsp
經過JConsole工具能夠查看運行中的Java程序(好比Eclipse)的一些信息:堆內存的分配,線程的數量以及加載的類的個數;ide
這裏有一份極好的白皮書:Memory Management in the Java HotSpot Virtual Machine。它描述了垃圾回收(GC)觸發的內存自動管理。Java的內存結構包含以下部分:
堆內存
堆內存一樣被劃分紅了多個區域:
不一樣區域的存放的對象擁有不一樣的生命週期:
生命週期來劃分對象,能夠消耗很短的時間和CPU作一次小的垃圾回收(GC)。緣由是跟C同樣,內存的釋放(經過銷燬對象)經過2種不一樣的GC實現:Young GC、Full GC。
爲了檢查全部的對象是否可以被銷燬,Young GC會標記不能銷燬的對象,通過屢次標記後,對象將會被移動到老年代中。
哪兒的OutOfMemoryError
對內存結構清晰的認識一樣能夠幫助理解不一樣OutOfMemoryErrors:
Exception in thread 「main」: java.lang.OutOfMemoryError: Java heap space
Exception in thread 「main」: java.lang.OutOfMemoryError: PermGen space
緣由:類或者方法不能被加載到老年代。它可能出如今一個程序加載不少類的時候,好比引用了不少第三方的庫;
Exception in thread 「main」: java.lang.OutOfMemoryError: Requested array size exceeds VM limit
緣由:建立的數組大於堆內存的空間
Exception in thread 「main」: java.lang.OutOfMemoryError: request <size> bytes for <reason>. Out of swap space?
緣由:分配本地分配失敗。JNI、本地庫或者Java虛擬機都會從本地堆中分配內存空間。
Exception in thread 「main」: java.lang.OutOfMemoryError: <reason> <stack trace>(Native method)
緣由:一樣是本地方法內存分配失敗,只不過是JNI或者本地方法或者Java虛擬機發現;
關於OutOfMemoryError的更多信息能夠查看:「Troubleshooting Guide for HotSpot VM」, Chapter 3 on 「Troubleshooting on memory leaks」
參考連接: