标签:
方法区:
方法区存放了要加载的类的信息(名称、修饰符等)、类的静态变量、类中定义为final类型的常量、类中的field信息、类中的方法信息。当开发人员在程序中通过Class对象的getName、isInterface等方法来获取信息时,这些数据都来源于方法区域。
方法区域是全局共享的,在一定条件下,它也会被GC,当方法区域要使用的内存超过其允许的最大值时,就会抛出OutOfMemory的错误信息。
方法区又称为持久代,默认最小值为16M,最大值为64M,可通过-XX:PermSize及-XX:MaxPermSize来指定最小值和最大值
堆:
堆用于存储对象实例及数组值,java中所有通过new创建的对象的内存都在此分配,Heap中对象所占用的内存由GC进行回收,在32位操作系统上最大为2GB;在64位操作系统上则没有限制,其大小可通过-Xms和-Xmx来控制,-Xms为JVM启动时申请的最小Heap内存,默认为物理内存的1/64但小于1GB;-Xmx为JVM可申请的最大Heap内存,默认为物理内存的1/4但小于1GB。
为了避免在运行时频繁调整Heap的大小,通常将-Xms和-Xmx的值设成一样。
新生代:
大多数情况下,java程序中新建的对象都从新生代分配内存,新生代由Eden Space和两块相同大小的Survivor Space(From和To区)构成。
可通过-Xmn参数来指定新生代的大小,可通过-XX:SurvivorRatio来调整Eden Space及Survivor Space的大小。
旧生代:
用于存放新生代中经过多次垃圾回收仍然存活的对象。例如:缓存对象,新建的对象也有可能在旧生代上直接分配内存。主要有两种状况:1. 大对象,可通过参数设置当对象超过多大时,就直接在旧生代分配内存。2. 大的数组对象。
旧生代所占用的内存大小为-Xmx对应的值减去-Xmn对应的值。
PC寄存器和JVM方法栈:
每个线程均会创建PC寄存器和JVM方法栈,PC寄存器占用的可能为CPU寄存器或操作系统内存,JVM方法栈占用的为操作系统内存,JVM方法栈为线程私有,其在内存分配上非常高效。当方法运行完毕,其对应栈帧所占用的内存也会自动释放。
当JVM方法栈空间不足时,会抛出StackOverflowError的错误。
内存分配:
Java对象所占用的内存主要从堆上进行分配,堆是所有线程所共享的,因此在堆上分配内存时,需要进行加锁,这会导致创建对象开销比较大。当堆空间不足时,会触发Gc,如果GC后空间仍然不足,则抛出OutOfMemory错误信息。
JDK为了提升内存分配的效率,会为每个新创建的线程在新生代的Eden Space上分配一块独立的空间,这块空间称为TLAB,其大小由JVM根据运行情况计算而得。
在TLAB上分配内存时不需要加锁,因此JVM在给线程的对象分配内存时会尽量在TLAB上分配,如果对象过大或TLAB空间已用完,则仍然在堆上进行分配。因此,在编写java代码时,通常多个小的对象比大的对象分配起来更加高效。
标签:
原文地址:http://www.cnblogs.com/chy2055/p/5129574.html