转一篇关于内存模型很好的文章【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”
参考连接: