JVM的配置及工作原理及回收策略

应用代码-需要jvm,解决方法-用tomcat配置

一、JVM的配置:

jvm配置(即分配堆栈)【前提:kill -9 进程id】
1.tomcat/bin/catalina.sh(linux)
2.JAVA_OPTS='-server -Xmx500M -Xms500M -Xmn200M =XX:MaxPermSize=128M -XX:PermSize=128M'
-Xms=500m  堆初始化时启动的内存 是物理内存的1/64。即剩余物理内存的1/64

-Xmx=500m 整个堆的最大的内存  是物理内存的1/4 。即剩余物理内存的1/4。整个堆即为Xmx   

-Xmn            是整个堆的3/8  新生代

(物理内存=总内存-使用内存) 

堆栈结构图

heap堆分为新生代和老年代

新生代   -Xmn      

老年代 =Xmx-Xmn

新生代内存又包括:eden,S0,S1

总结:

1. -Xmn=edsn+S0+S1=200m

2. 新生代三个区内存分配的方法:

A:在JAVA_OPTS后面追加-XX:SurvivorRatio=xx  设置比例

B:不设置默认 -XX:SurvivorRatio=8(注:建议使用默认)

总结:1.jvm内存是从物理内存借用的,tomcat启动成功及JVM从物理内存分配内存也成功**

          2.面试题:-Xmx和-Xms设置一样的目的【大并发】

Xms默认值是物理内存的1/64,内存值较小;当大并发流量增大,new的数据较多,就会出现-Xms内存不够用的情况,此时还需要临时向物理内存申请借用,借用时会遇到两种情况

1)物理内存此刻已无过多空间内存,则java代码new产生的数据就不能存入jvm中,此刻程序报错

2)从物理内存借到内存,但此过程java程序在等待,消耗时间

-XX:PermSize=128m  栈初始化内存  是物理内存的1/64

-XX:MaxPermSize=12m  栈最大化内存  是物理内存的1/4

-XX:PermSize=-XX:MaxPermSize  相等 【大并发】   实际情况【256m/512m】--节省内存空间
1. 当-XX"PermSize过小内存不够用时,想物理内存借用内存,若物理地址此刻没有空间,则对象引用就不能放入栈中,此刻程序报错
2  当-XX:MaxPermSize过小内存不够用时,向物理内存借用内存,然后java对象引用才能放入栈中,影响效率

查看jvm配置的方法
1. 查询java进程  ps -ef |  grep   java
2. 查询进程id jmap -heap
jps  查看当前进程
kill -9 进程号  杀死当前进程 强制结束
sh shutdown.sh  不一定能结束进程
vim
set nu  注释序号

jvm配置步骤

1. tomcat若启动 则:1)jps或者netstat -ntlp | grep port 或者 ps -ef | grep java ==>得到java pid

                                 2)kill -9 进程id

2. tomcat/bin.catalina.sh(linux)
3. vim编辑 输入相关配置JAVA_OPTS

4. tomcat/bin/目录下执行,sh startup.sh

JVM原理

jvm工作原理
1. AG  堆中数据引用存入栈中
2. B,C,D,E,F
B↓
并发数大则类似B数据就会创建越多,甚至达到eden去内存上限
规则1:eden区数据不被栈引用,则说明cpu中代码已运行完成,此时栈中对象如per1释放,故此类数据在eden区被清扫
规则2:esen区数据仍然被栈引用,则说明cpu中代码仍在运行中,故此类数据要复制到S0交换区
总结:通过规则1,2最终目的把eden区的内存空间腾出来,然后对接后续线程代码new的数据。**
S0↓
当并发数大则类似B数据就会创建越多,甚至达到S0区内存上限
规则1:S0区数据
不被栈引用,则说明cpu中代码已运行完成,故此类数据在S0区被清扫
规则2:S0区数据仍然被栈引用,则则说明cpu中代码仍在运行中,故此类数据要复制到S1交换区
总结:通过规则1,2最终目的把S0区的内存空间腾出来,然后对接后续eden区中还持续被引用的对象
S1↓
当并发数则类似B数据就会创建越多,甚至达到S1区内存上限
规则1:eden区数据
不被栈引用,则说明cpu中代码已运行完成,故此类数据在S1区被清扫
规则2:esen区数据仍然被栈引用,则则说明cpu中代码仍在运行中,故此类数据要复制到老年代区
总结:通过规则1,2最终目的把S1区的内存空间腾出来,然后对接后续S0区中还持续被引用的对象
老年代↓
当并发数则类似B数据就会创建越多,甚至达到老年代区内存上限
规则1:触发fgc(新生代是gc),将不被引用的数据(fgc)清扫掉,即栈中对象引用也结束,降低老年代内存使用率
规则2:当达到老年代内存上限时,如果代码创建的数据对象还没栈引用,说明代码还在运行。
更极端情况,若老年代中的数据对象全被引用不释放,则此刻达到内存上限时,则清扫/释放不了,同时S1继续往老年代中复制对象时,老年代无内存利用,最后造成内存溢出即OOM

面试题:

1. 是否可以不用S0,S1区

S0 S1是新生代的两个交换区,这2个区可以延缓进入老年代数据对象的次数,则降低老年代清扫内存中的数据对象的次数,如果不使用S0,S1,就会加速数据进入老年代的次数,从而增加老年代清扫数据对象的次数,最后造成内存溢出即OOM

注:默认值:-XX:MaxTenuringThreashold=15(修改值即增加至配置后面)

2.堆栈内什么情况下会满:

3.tomcat和jvm的关系

1)tomcat是应用服务器,在webapps下可部署java代码,tomcat下的Java代码运行时需要jvm,而刚好tomcat可配置jvm。

2)jvm是java虚拟机分为堆和栈,栈中存放对象引用,堆中存放程序创建的数据对象


jvm内存回收策略

串行回收 (JDK1.5前的默认算法)
原理
1. 达到eden区上限时,在eden加安全挡板,然后jvm gc线程进行回收(单线程)
2. 达到老年代内存上限时,在老年代加安全挡板,然后jvm gc线程进行回收

配置:
串行收集器(Serial Collector )
-XX:+UseSerialGC:设置串行收集器,串行收集器只适用于小数据量的情况
JAVA_OPTS=‘-server -Xmx=500M -Xms=500M -Xmn=200M -XX:MaxPermSize=128M -XX:PermSize=128M -XX:+UseSerialGC’
评价:
好处:达到gc;

不足:单线程GC时,若遇到内存空间大,则gc慢,挡板无法打开,后续代码new.S1下移时,造成代码报错率上升且单线程回收适应小数据量的应用。

总结

不是只有一个线程,执行垃圾回收时程序停止时间比较长,适合小数据量的并发应用

并行回收 --吞吐量(处理能力)优先 Reponse Time可能会增大
原理 :前提:垃圾回收线程和用户线程不共享服务器资源
1. 达到eden区上限时,在eden区加安全挡板,然后jvm gc线程进行回收(可配置多线程)
2. 达到老年代内存上限时,在老年代加安全挡板,然后jvm gc线程进行回收(可配置多线程)
配置:
并行收集器(吞吐量优先-Throughput Collector )
-XX:+UseParallelGC:设置并行收集器,此配置仅对年轻代有效(即年轻带使用并行收集,老年代使用串行收集)
-XX:ParallelGCThreads=20:配置并行收集器的线程数,即:同时有多少个线程一起进行垃圾回收,此值建议配置与cpu数目相等(多线程竞争会导致线程失败)
-XX:+UseParallelOldGC:配置老年代垃圾收集方式为并行收集,JDK6.0开始支持对老年代并行收集


JAVA_OPTS=‘-server -Xmx500M -Xms500M -Xmn200M =XX:MaxPermSize=128M -XX:PermSize=128M -XX:+UseParallelGC -XX:ParallelGCThreads=20 -XX:+UseParallelOldGC ’

评价:
好处:达到gc

不足:并行特性是同一时刻,故多线程同时开启gc,但也需同时结束;虽进行gc,但时间可能稍久。

总结:
1)不足:eden老年代进行2次暂停挡板进行gc回收,程序需要再挡板外进行等待(可能造成时间过长)

2)垃圾回收多线程,同时处理不被引用的数据,效率比串行高,回收时jvm会停止运行

3)垃圾回收线程和用户线程不共享服务器资源


并发回收 --响应时间优先
原理:
1. 达到eden区上限时,在eden区加安全挡板,然后jvm gc线程进行回收(可配置多线程+并行回收)
2. 达到老年代内存上限时,在老年代加安全挡板,然后jvm gc线程进行回收(可配置多线程+并发回收)
总结:

1)系统和垃圾回收一起执行,老年代则只有2次短暂暂停,适合于响应要求高的系统

2)垃圾回收线程和用户线程共享服务器资源


配置:
并发收集器(响应时间优先-Concurrent Low Pause Collector)
-XX:UsePartNewGC:设置年轻代为并行收集,可与CMS收集同时使用
-XX:UseConMarkSweepGC:即CMS收集,设置年老代为并发收集,CMS收集是JDK1.4后期版本开始引入的新GC算法。他主要适合对相应时间的重要性需求大于吞吐量的需求
--XX:ParallelGCThreads=N 来调整年轻代的并行收集线程数
--XX:ParallelCMSThreads=N 来调整老年代的CMS收集线程数,CMS默认启动的回收线程数目[(ParallelGCThreads+3)/4]
JAVA_OPTS=“-server -Xmx500M -Xms500M -Xmn200M =XX:MaxPermSize=128M -XX:PermSize=128M -XX:UsePartNewGC +并发线程数? -XX:UseConMarkSweepGC”


-XX:CMSInitiatingOccupanyFraction=70:表示年老代内存空间使用到70%时就开始执行CMS收集,以确保年老代有足够的空间接纳来自年轻代的对象,避免Full GC发生。
-XX:+UseCMSCompactAtFullCollection:内存使用率降低。此参数设置运行0次Full GC后对内存空间进行压缩和整理,即每次Full GC后立刻开始压缩和整理内存。打开内存空间的压缩和整理,
在Full GC后执行,可能会影响性能,但可以消除内存碎片
-XX:+CMSPermGenSweepingEnabled -XX:+CMSClassUnloadingEnabled  建议开启CMS回收Perm区选项


面试题:
1. 堆栈内存发生什么会满?
存放的地址引用一直没释放,(对应堆的数据没有被回收),此现象现在持续增加则会造成栈内存达到上限==>堆内存相应达到上限
正常情况:堆gc,栈对象引用结束
不正常情况:堆gc不了数据,栈对象引用不能释放,外部压力持续增大,此时程序OOM (注:解决代码瓶颈(程序不结束,引用不结束,堆数据不gc))


2. 如何降低老年代fgc的次数和时间?
1)增大gc线程
2)增大-XX:MaxTenuringThreashold=15
3)-XX:CMSInitiatingOccupanyFraction=70:表示年老代内存空间使用到70%时就开始执行CMS收集,以确保年老代有足够的空间接纳来自年轻代的对象,避免Full GC发生。


3. 如何快速知道代码是否会产生jvm相关的瓶颈?(即堆和栈的瓶颈)
-Xmx=-Xms=100M  -Xmn=40M,则老年代为60M,设置内存小,进行大并发压测下,如果代码无瓶颈,gc的次数比较多,若代码有瓶颈,则很快发生内存溢出,这样即可快速知道新生代和老年代gc的情况


4. tomcat和jvm有啥关系?
1. 工作范围不同
1)tomcat是应用服务器,在webapps下可部署代码
2)jvm是Java虚拟机分为堆和栈,栈中存放对象引用,对重存放程序常见的数据对象。
因tomcat下的java代码运行时,需要jvm,而刚好tomcat可配置jvm


5. 一台linux机器上,有3个tomcat,想问下要配置几个jvm?
配置3个jvm,手工不配则用系统默认的jvm内存,只是内存较小,一般不建议
一天机器上部署多个tomcat原因如下:
1. 此机器若负载过高或挂掉,当前tomcat上部署的服务全部不能工作
2. 当物理内存吃紧,也会影响tomcat
最后建议一台机器上部署一个核心服务,如果机器配置过高的话,可进行主要业务和非主要内务配合。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值