1、JVM内存结构由程序计数器、堆、栈、本地方法栈、方法区等部分组成。
1)程序计数器
几乎不占有内存。用于取下一条执行的指令。
2)堆
全部经过new建立的对象的内存都在堆中分配,其大小能够经过-Xmx和-Xms来控制。堆被划分为新生代和旧生代,新生代又被进一步划分为Eden和Survivor区,最后Survivor由FromSpace和ToSpace组成。
通常状况将新生代分为Eden ,两块Survivor区域;
新生代。新建的对象都是用新生代分配内存,Eden空间不足的时候,会把存活的对象转移到Survivor中,新生代大小能够由-Xmn来控制,也能够用-XX:SurvivorRatio来控制Eden和Survivor的比例旧生代。用于存放新生代中通过屡次垃圾回收仍然存活的对象。
3)栈
每一个线程执行每一个方法的时候都会在栈中申请一个栈帧,每一个栈帧包括局部变量区和操做数栈,用于存放这次方法调用过程当中的临时变量、参数和中间结果。
4)本地方法栈
用于支持native方法的执行,存储了每一个native方法调用的状态。
5)方法区
存放了要加载的类信息、静态变量、final类型的常量、属性和方法信息。JVM用永久代(PermanetGeneration)来存放方法区,(在JDK的HotSpot虚拟机中,能够认为方法区就是永久代,可是在其余类型的虚拟机中,没有永久代的概念,有关信息能够看周志明的书)可经过-XX:PermSize和-XX:MaxPermSize来指定最小值和最大值。java
2、JVM垃圾回收机制
JVM分别对新生代和旧生代采用不一样的垃圾回收机制
新生代的GC:
新生代一般存活时间较短,所以基于复制算法来进行回收,所谓复制算法就是扫描出存活的对象,并复制到一块新的彻底未使用的空间中,对应于新生代,就是在Eden和其中一个Survivor,复制到另外一个之间Survivor空间中,而后清理掉原来就是在Eden和其中一个Survivor中的对象。新生代采用空闲指针的方式来控制GC触发,指针保持最后一个分配的对象在新生代区间的位置,当有新的对象要分配内存时,用于检查空间是否足够,不够就触发GC。当连续分配对象时,对象会逐渐从eden到 survivor,最后到老年代。算法
用javavisualVM来查看,能明显观察到新生代满了后,会把对象转移到旧生代,而后清空继续装载,当旧生代也满了后,就会报outofmemory的异常。spa
旧生代与新生代不一样,对象存活的时间比较长,比较稳定,所以采用标记(Mark)算法来进行回收,所谓标记就是扫描出存活的对象,而后再进行回收未被标记的对象,回收后对用空出的空间要么进行合并,要么标记出来便于下次进行分配,总之就是要减小内存碎片带来的效率损耗。线程
3、GC堆指针
Java 中的堆是 JVM 所管理的最大的一块内存空间,主要用于存放各类类的实例对象。
在 Java 中,堆被划分红两个不一样的区域:新生代 ( Young )、老年代 ( Old )。新生代 ( Young ) 又被划分为三个区域:Eden、From Survivor、To Survivor。
这样划分的目的是为了使 JVM 可以更好的管理堆内存中的对象,包括内存的分配以及回收。
堆的内存模型大体为:对象
从图中能够看出: 堆大小 = 新生代 + 老年代。其中,堆的大小能够经过参数 –Xms、-Xmx 来指定。
默认的,新生代 ( Young ) 与老年代 ( Old ) 的比例的值为 1:2 ( 该值能够经过参数 –XX:NewRatio 来指定),即:新生代 ( Young ) = 1/3 的堆空间大小。老年代 ( Old ) = 2/3 的堆空间大小。其中,新生代 ( Young )被细分为 Eden 和 两个 Survivor 区域,这两个 Survivor 区域分别被命名为 from 和 to,以示区分。
默认的,Edem : from : to = 8 :1 : 1 ( 能够经过参数–XX:SurvivorRatio 来设定 ),即: Eden = 8/10 的
新生代空间大小,from = to = 1/10 的新生代空间大小。
JVM 每次只会使用 Eden 和其中的一块 Survivor 区域来为对象服务,因此不管何时,老是有一块Survivor区域是空闲着的。
所以,新生代实际可用的内存空间为 9/10 ( 即90% )的新生代空间。blog
4、JVM 参数选项
下面只列举其中的几个经常使用和容易掌握的配置选项:
-Xms
初始堆大小。如:-Xms256m内存
-Xmx
最大堆大小。如:-Xmx512m虚拟机
-Xmn
新生代大小。一般为 Xmx 的 1/3 或 1/4。新生代 = Eden + 2 个 Survivor 空间。实际可用空间为 = Eden + 1 个 Survivor,即 90% io
-Xss
JDK1.5+ 每一个线程堆栈大小为 1M,通常来讲若是栈不是很深的话, 1M 是绝对够用了的。
-XX:NewRatio
新生代与老年代的比例,如 –XX:NewRatio=2,则新生代占整个堆空间的1/3,老年代占2/3
-XX:SurvivorRatio
新生代中 Eden 与 Survivor 的比值。默认值为 8。即 Eden 占新生代空间的 8/10,另外两个 Survivor 各占 1/10
-XX:PermSize
永久代(方法区)的初始大小
-XX:MaxPermSize
永久代(方法区)的最大值
-XX:+PrintGCDetails
打印 GC 信息
-XX:+HeapDumpOnOutOfMemoryError让虚拟机在发生内存溢出时 Dump 出当前的内存堆转储快照,以便分析用