JVM(二)

在JVM(一)中简单的描述了JVM的加载过程和JVM的内存区域区分。这篇主要对于垃圾回收机制、垃圾回收算法、垃圾回收器等进行简单的说明

一、JVM是怎么对对象进行回收的?

JVM中使用垃圾回收机制来确保对无用对象等的回收,说到垃圾回收机制,需要先了解堆的区域划分和分布

一、堆的分布

在jvm堆内存分布中,主要分代有年轻代、老年代(永久代一般指方法区)

在创建对象时一般会创建两种对象:

1)、存活时间短:一般时类中的变量对象.   

2)、存活时间长:一般是创建静态变量/大对象/多次gc不被回收的对象(线程共享)

为了针对这个现象,JVM的堆内存采用了分代的模型,存活时间短的对象一般在年轻代,经过多次小gc的一般放在老年代。原因如下:

(1)默认区域大小比例1:2

因为年轻代的对象数目多、且存活时间短,所以需要经常去回收这个区域的无用对象。所以在对年轻代和老年代进行划分的时候是1:4进行划分的,这样年轻代因为内存比较小就会经常触发MinorGC从而达到经常对年轻代进行回收对象的效果

而老年代是存放那些在年轻代gc多次还没有被回收的对象,这些对象的存活时间长,如果经常回收这些数据每次只能回收少量对象,这样效率就会低下,所以将老年代的内存分多些就可以多放一些对象,这样相当于减少了FullGC的次数了

(2)使用不同算法进行回收

年轻代要经常进行回收,而老年代需要回收的比较少,所以对不同的年代采用不同的回收算法。(当然也有年轻代和老年代都shi'y)

上面对于堆的年代分类进行简单说明,至于各个年代使用的是什么算法,具体的信息下面说明


永久代:永久代不属于堆内存,一般指的是方法区(存放类信息、静态常量,常量池)。那方法区什么时候进行垃圾回收?(JVM垃圾回收也针对方法区)
——首先该类的所有实例对象都已经从Java堆内存里被回收,其次加载这个类的ClassLoader已经被回收,最后,对该类的Class对象没有任何引用(1、对应类加载器被回收 2、对应的实例对象在堆中被回收 3、class对象没有被引用)


二、对象怎么从年轻代到老年代的?

一般的对象放置都是先放进新生代,然后经过15MinorGC后还未被回收的对象会被放进老年代,只有少部分特殊的对象(特别大的超大对象)会不经过年轻代直接进入老年代中

下面是堆中对于年轻代和老年代的划分:

新生区

分为两部分: 伊甸区(Eden space)和幸存者区(Survivor pace) ,所有的类都是在伊甸区被new出来的。幸存区有两个: 0区(Survivor 0 space)和1区(Survivor 1 space)。当伊甸园的空间用完时,程序又需要创建对象,JVM的垃圾回收器将对伊甸园区进行垃圾回收(Minor GC),将伊甸园区中的不再被其他对象所引用的对象进行销毁。然后将伊甸园中的剩余对象移动到幸存 0区。若幸存 0区也满了,再对该区进行垃圾回收,然后移动到1区。此后eden区来的对象存到1区,当1区满后则进行gc然后将对象放到0区,依次循环到达某个次数时则会将仍然存活的对象移动到老年区。(复制算法)

老年区

新生区经过多次GC仍然存活的对象移动到老年区。若老年区也满了,那么这个时候将产生MajorGC(FullGC),进行老年区的内存清理。若老年区执行了Full GC之后发现依然无法进行对象的保存,就会产生OOM异常“OutOfMemoryError”


讲到这里,先不急着讲年轻代、老年代的gc过程,回收算法、垃圾回收器等知识,我们先来上手实践一下怎么配置JVM参数。看看怎么给整个堆、方法区、栈、堆中各个年代的内存大小进行配置。

三、配置JVM参数

JVM内存分配中,有几个参数是比较核心的,如下所示。

-Xms:Java堆内存的大小 

 -Xmx:Java堆内存的最大大小 

  -Xmn:Java堆内存中的新生代大小,扣除新生代剩下的就是老年代的内存大小了 

  -XX:PermSize:永久代大小   

 -XX:MaxPermSize:永久代最大大小 

  -Xss:每个线程的栈内存大小

这些参数的设置对应下面JVM内存大小分布

1、-Xms和-Xmx,分别用于设置Java堆内存的刚开始的大小,以及允许扩张到的最大大小。对于这对参数,通常来说,都会设置为完全一样的大小

2、-Xmn,这个参数也是很常见的,他用来设置Java堆内存中的新生代的大小,然后扣除新生代大小之后的剩余内存就是给老年代的内存大小。

3、-XX:PermSize和-XX:MaxPermSize,分别限定了永久代大小和永久代的最大大小,通常这两个数值也是设置为一样的。如果是JDK 1.8以后的版本,那么这俩参数被替换为了-XX:MetaspaceSize和-XX:MaxMetaspaceSize

4、-Xss,这个参数限定了每个线程的栈内存大小


知道了JVM参数的大概意思,那么现实中我们怎么配置JVM的启动参数?

1、开发阶段:idea中

然后应用启动即可。

2、部署阶段

可以使用java -Xms512M -Xmx512M -Xmn256M -Xss1M -XX:PermSize=128M -XX:MaxPermSize=128M -jar App.jar 进行部署。

(自己看了下公司的微服务部署:java -Xmx1g -jar ***.jar   java -Xmx512m -jar ***.jar)

获取JVM默认的参数设置

然后启动JVM,就会打印相应的参数信息

 


四、怎么大概的去预估堆内存大小?

 

aa
 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值