我们接下来说的JVM中运行时数据区中的堆区(Heap Area)。
对于Java应用程序来说,Java堆(Java Heap)是虚拟机所管理的内存中最大的一块。Java堆是被所有线程共享的一块区域,在虚拟机启动时创建。此内存区域的唯一的目的就是存放对象实例,Java世界里“几乎”所有的对象实例都在这里分配内存。在《Java虚拟机规范》中对Java堆的描述是:“所有的对象实例以及数组都应当在堆上分配”。
堆也是Java内存管理的核心区域
。堆内存的大小是可以调节的
。《Java虚拟机规范》
规定,堆可以处于 **物理上不连续**
的内存空间中,但是 **逻辑上**
它应该是被视为 连续的
。多个线程,他们是共享同一堆空间的
。缓冲区
(**Thread Local Allocation Buffer, TLAB**
)从上图中我们可以知道,堆的空间可以被细分为很多区:
年轻代(Young Gen)
老年代(Old Gen)
永久代(Perm Gen)
其中年轻代被分为 Eden 空间
、Survivor 1空间
(From区
)、Survivor 0空间
(To 区
),备注:谁空谁就是 To区
。
年轻代、老年代、永久代
轻GC
)只管年轻代,Full GC(重GC
) 同时管理年轻代和老年代为什么要分代?有什么好处?
Runtime类:该类对应的JVM运行时数据区
long initialMemory = Runtime.getRuntime().totalMemory();
long maxMemory = Runtime.getRuntime().maxMemory();
long freeMemory = Runtime.getRuntime().freeMemory();
参数 | 说明 |
---|---|
-Xms | 堆内存初始大小,单位m(兆)、g(G) |
-Xmx(MaxHeapSize) | 堆内存最大允许大小,一般不要大于物理内存的80% |
-XX:PermSize | 非堆内存初始大小,一般应用设置初始化200m,最大1024m就够了 |
-XX:MaxPermSize | 非堆内存最大允许大小 |
-XX:NewSize(-Xns) | 年轻代内存初始大小 |
-XX:MaxNewSize(-Xmn) | 年轻代内存最大允许大小,也可以缩写 |
-XX:SurvivorRatio=8 | 年轻代中Eden区与Survivor区的容量比例值,默认为8,即8:1 |
-Xss | 堆栈内存大小 |
以下几种垃圾回收算法只是抛砖引玉,具体详细的算法说明还需要自行搜索并加以学习,算法还有很多,所以学习的东西有很多哦。
红色是标记的非活动对象,绿色是活动对象。
GC分为两个阶段,标记和清除。首先标记所有可回收的对象,在标记完成后统一回收所有被标记的对象。同时会产生不连续的内存碎片。碎片过多会导致以后程序运行时需要分配较大对象时,无法找到足够的连续内存,而不得已再次触发GC。
将内存按容量划分为两块,每次只使用其中一块。当这一块内存用完了,就将存活的对象复制到另一块上,然后再把已使用的内存空间一次清理掉。这样使得每次都是对半个内存区回收,也不用考虑内存碎片问题,简单高效。缺点需要两倍的内存空间。
也分为两个阶段,首先标记可回收的对象,再将存活的对象都向一端移动,然后清理掉边界以外的内存。此方法避免标记-清除算法的碎片问题,同时也避免了复制算法的空间问题。
一般年轻代中执行GC后,会有少量的对象存活,就会选用复制算法,只要付出少量的存活对象复制成本就可以完成收集。
而老年代中因为对象存活率高,没有额外过多内存空间分配,就需要使用标记-清理或者标记-整理算法来进行回收。
在年轻代中经过GC后还存活的对象会被复制到老年代中。当老年代空间不足时,JVM会对老年代进行完全的垃圾回收(Full GC)。如果GC后,还是无法存放从Survivor区复制过来的对象,就会出现OOM(Out of Memory)。
OOM(Out Of Memory)异常常见有以下几个原因:
老年代内存不足:java.lang.OutOfMemoryError:Javaheapspace
永久代内存不足:java.lang.OutOfMemoryError:PermGenspace
代码bug,占用内存无法及时回收
。OOM在这几个内存区都有可能出现,实际遇到OOM时,能根据异常信息定位到哪个区的内存溢出。
可以通过添加个参数 -XX:+HeapDumpOnOutMemoryError
,让虚拟机在出现内存溢出异常时Dump出当前的内存堆转储快照以便事后分析。
熟悉了JAVA内存管理机制及配置参数,下面是对JAVA应用启动选项调优配置:
JAVA_OPTS=“-server -Xms512m -Xmx2g -XX:+UseG1GC -XX:SurvivorRatio=6 -XX:MaxGCPauseMillis=400 -XX:G1ReservePercent=15 -XX:ParallelGCThreads=4 -XX:
ConcGCThreads=1 -XX:InitiatingHeapOccupancyPercent=40 -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -Xloggc:…/logs/gc.log”
设置堆内存最小和最大值,最大值参考历史利用率设置
设置GC垃圾收集器为G1
启用GC日志,方便后期分析
完结!