java 堆体系结构,对象的生命周期和GC,永久代,堆参数调优

1.堆体系结构

heap 堆

一个JVM实例只存在一个堆内存,堆内存的大小是可以调节的.

类加载器读取了类文件后,需要把类,方法,常变量放到堆内存中,保存所有引用类型的真实信息,以便执行器执行.

堆内存分为三个部分:

Young Generation Space 新生区
		
Tenure Generation Space 养老区

Permanent Space 永久区

首先对新生区进行简单概述.
新生区是类的诞生,成长,消亡的区域(98%的对象都活不过新生区)

新生区分为:

			Eden Space(伊甸区)
			
			Survivor 0 Space(幸存者0区,别名 from)
			
			Survivor 1 Space(幸存者1区,别名 to )

当伊甸区的内存首次占用达到98%左右时,Eden Space 会触发 YGC(轻量级GC)进行清理,存活下来的对象进入幸存者0区 ,同时年龄+1.

当伊甸区的内存占用再次达到阈值时,会再次进行清理(伊甸区,幸存者0区),存活下来的对象进入到
幸存者1区,年龄+1

如此反复下来, 当年龄达到15依然存活的对象会被移入到养老区.

如果养老区的内存到达阈值后,会进行FGC(Full GC 重量级GC),进行养老区清理,full GC 多次后依然无法清理出空间,会报出OOM(OutOfMemoryError)[可以通过String累加开启 -XX:+printGCDetails 来查看GC进程]

如果出现了OOM异常,说明java虚拟机的内存不够了,原因有二:

1.java虚拟机的堆内存设置不够,可以通过参数 -Xms -Xmx  调节
2.代码中创建了大量大对象(大对象会被直接放入老年区),并且长时间不能被垃圾收集器收集(存在被引用),养老区到达阈值,
进行 full GC 后依然无法清理,报出OutOfMemoryError

对象的生命周期和GC

from区和to区的位置和名字不是固定的,每次GC之后都会交换.
GC之后有交换,谁空谁是to(回收算法-复制-清除-交换)

Java堆从GC的角度看还可以细分:新生代(Eden区,From Survivor区和To Survivor区)和老年代.

新生代栈 (1/3) 堆空间

Eden占了8/10      From Survivor占了1/10      To Survivor占了1/10  

老年代(2/3)堆空间

MinorGC的过程(复制->清除->交换)
  1. Eden , Survivor From 复制到 Survivor To
  2. 清空Eden,Survivor From
  3. 交换Survivor Form <=> Survivor To

1.首先,当Eden区满的时候会触发第一次GC,把还活着的对象拷贝到Survivor from 区,当Eden区再次触发GC时,会对Eden区和Survivor from 区进行清除,把存活下来的对象拷贝到Survivor to 区,同时把这些对象的年龄+1

2.然后对Eden区和Survivor from 区进行清除 , 然后交换Survivor From区与Survivor To 区

3.原Survivor To 区成为了下一次GC时的Survivor From区
部分对象会在From 区 和 To区中来回复制,当这个对象的年龄达到15时,如果还活着,就会把对象存入到老年代.

在这里插入图片描述

永久代
永久代包括:
perm ,Eden ,Survivor From .Survivor To ,Old

方法区和堆一样,是各个线程共享的内存区域.同于存储虚拟机加载的类信息,普通常量,静态常量,编译器编译后的代码等等,JVM规范讲方法区描述为堆的一个逻辑部分,但它还有一个别名:non-heap(非堆),目的就是要和堆分开.

对于Hotspot虚拟机,很多开发者习惯将方法区成为永久代,这种说法并不准确,从严格本质上两者是不同的,或者说是用永久代来实现方法区,永久代是方法区的一个实现.在jdk1.7中,原本在永久代中的常量池被移走.

永久代在java7之前存在,8中被元空间所替代.
永久存储区是一个常驻内存区域,用于存放JDK字舍所携带的Class,Interface数据,他存放的是java运行环境所必须的类信息,被装载到此区域的数据不会被垃圾回收器回收掉,关闭JVM时才会释放此区域所占的内存.

堆参数调优

Java7:

在这里插入图片描述

Java8:
Jdk1.8之后将最初的永久代取消掉,由元空间代替.
在这里插入图片描述
元空间的本质与永久代类似.
最大的区别在于永久代使用的是JVM堆内存,但是元空间并不在虚拟机中而使用本机的物理内存,因此,默认情况下,元空间的大小仅受本地内存限制.类的元数据放入native memory中,字符串常量池和类的静态变量放入java堆内存中.
这样可以加载多少类的元数据就不再由MaxPermSize控制,而是由系统的实际可用空间来控制(1/4)

-Xms设置初始分配大小,默认为物理内存的1/64
-Xmx最大分配内存,默认为物理内存的1/4
-XX:+PrintGCDetails输出详细的GC日志

: -Xms1024m -Xmx1024m -XX:+PrintGCDetails
XMs与Xmx数值尽量保持一致

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值