目录
一 JVM堆内存划分
二 参数设置
一 JVM堆内存划分
逻辑上:新生代、老年代、永久代
物理上:新生代、 老年代
JDK1.7之前,有永久代,但已经逐步“去永久代”
JDK1.8之后,无永久代,由元空间替代
java堆从GC的角度,可以细分为:
- 新生代(Eden区、From Survivor区、To Survivor区)
- 老年代
1、新生代:用来存放新生的对象。一般占据堆的1/3空间。由于频繁创建对象,所以新生代会频繁触发MinorGC(新生代GC)进行垃圾回收。
(1)Eden区:Java新对象的出生地(如果新创建的对象占用内存很大,则直接分配到老年代)。
当Eden区内存不够的时候就会触发MinorGC,对新生代区进行一次垃圾回收。
(2)From Survivor区:上一次GC的幸存者,作为这一次GC的被扫描者
(3)To Survivor区:保留了一次MinorGC过程中的幸存者
MinorGC(新生代GC)的过程:
首先,把Eden和Servivor From区域中存活的对象复制到Servicor To区域(如果有对象的年龄达到了老年的标准,则赋值到老年代区),同时把这些对象的年龄+1(如果 ServicorTo 不够位置了就放到老年区);
然后,清空 Eden 和 Servicor From 中的对象;
最后,Servicor To 和 Servicor From 互换,原 ServicorTo 成为下一次 GC 时的 Servicor From 区。
2、老年代:主要存放应用程序中生命周期长的内存对象。
老年代的对象比较稳定,所以MajorGC不会频繁执行。
在执行MajorGC前一般都先进行了一次MinorGC,使得有新生代的对象晋升入老年代,导致空间不够时才触发。
当无法找到足够大的连续空间分配给新创建的较大对象时也会提前触发一次MajorGC进行垃圾回收腾出空间。
3、永久代:指内存的永久保存区域,主要存放Class和Meta(元数据)的信息。
Class在被加载的时候被放入永久区域,它和存放实例的区域不同,GC不会在主程序运行期对永久区域进行处理。所以这也导致永久代区域会随着加载Class的增多而膨胀,最终抛出OOM异常。
4、Java8与元数据
在java8中,永久代已经被移除,被“元数据区”(元空间)所取代。
元空间的本质和永久代类似,元空间与永久代之间最大的区别在于:元空间并不在虚拟机中,而是在本地内存。因此,默认情况下,元空间大小仅受本地内存限制。
类的元数据放入native memory(本机内存),字符串池和类的静态变量放入java堆中,这样可以加载多少类的元数据就不再由MaxPermSize(最大非堆内存的大小) 控制, 而由系统的实际可用空间来控制。
二 参数设置
Xmn、Xms、Xmx、Xss都是JVM对内存的配置参数,我们可以根据不同需要区修改这些参数,以达到运行程序的最好效果。文章来源:https://www.toymoban.com/news/detail-451190.html
- -Xms:初始堆大小,默认为物理内存的1/64
- -Xmx:堆内存的最大值,默认为物理内存的1/4
- -Xmn:堆内新生代的大小。通过这个值也可以得到老生代的大小:(-Xmx)-(-Xmn)
- -Xss:设置每个线程可使用的内存大小,即栈的大小。在相同物理内存下,减小这个值能生成更多的线程,但操作系统对一个进程内的线程数还是有限制的,不能无限生成。
线程栈的大小是个双刃剑,如果设置过小,可能会出现栈溢出,特别是在该线程内有递归、大的循环时出现溢出的可能性更大;如果该值设置过大,就有影响到创建栈的数量,如果是多线程的应用,就会出现内存溢出的错误。文章来源地址https://www.toymoban.com/news/detail-451190.html
到了这里,关于JVM堆内存及参数配置 -Xss -Xms -Xmx -Xmn的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!