JVM内存划分
一.程序计数器 (1.记录下一条要运行的指令 2.线程私有,独立工作)
二.Java虚拟机栈(1.栈帧:局部变量表(基本数据类型和对象引用)、操作数栈、方法出口等信息 2.线程私有 3.StackOverflowError和OutOfMemoryError)
三.本地方法栈(1.作用与Java虚拟机栈相似)
四.Java堆 (1.线程共享、分配空间 2.新生代和老年代 3.GC 4.OutOfMemoryError)
五.方法区(1.线程共享,存储类的信息、常量池、方法数据、方法代码等 2.运行时常量池(Jdk7以前&以后) 3.OutOfMemoryError)
java 虚拟机年轻代和年老代?
我是一个普通的java对象,我出生在Eden区,在Eden区我还看到和我长的很像的小兄弟,我们在Eden区中玩了挺长时间。有一天Eden区中的人实在是太多了,我就被迫去了Survivor区的“From”区,自从去了Survivor区,我就开始漂了,有时候在Survivor的“From”区,有时候在Survivor的“To”区,居无定所。直到我18岁的时候,爸爸说我成人了,该去社会上闯闯了。于是我就去了年老代那边,年老代里,人很多,并且年龄都挺大的,我在这里也认识了很多人。在年老代里,我生活了20年(每次GC加一岁),然后被回收。
为什么两块Survivor?
为了保证Eden过来的内存不碎片化,太多,又容易填满,16复制对象后放入年老代
更大的年轻代必然导致更小的年老代,大的年轻代会延长普通GC的周期,但会增加每次GC的时间;小的年老代会导致更频繁的Full GC
更小的年轻代必然导致更大年老代,小的年轻代会导致普通GC很频繁,但每次的GC时间会更短;大的年老代会减少Full GC的频率
年轻:年老比例 1:2 GC的时间足够的小,短,Full GC的周期足够的长
JVM调优
对JVM内存的系统级的调优主要的目的是减少GC的频率和Full GC的次数,过多的GC和Full GC是会占用很多的系统资源(主要是CPU),影响系统的吞吐量。特别要关注Full GC,因为它会对整个堆进行整理,导致Full GC一般由于以下几种情况:
1、旧生代空间不足
调优时尽量让对象在新生代GC时被回收、让对象在新生代多存活一段时间和不要创建过大的对象及数组避免直接在旧生代创建对象
2、Pemanet Generation空间不足
增大Perm Gen空间,避免太多静态对象
统计得到的GC后晋升到旧生代的平均大小大于旧生代剩余空间
控制好新生代和旧生代的比例
3、System.gc()被显示调用
垃圾回收不要手动触发,尽量依靠JVM自身的机制
一、新生代设置过小:新生代GC次数非常频繁,增大系统消耗;二是导致大对象直接进入旧生代,占据了旧生代剩余空间,诱发Full GC 新生代设置过大:一是新生代设置过大会导致旧生代过小(堆总量一定),从而诱发Full GC;二是新生代GC耗时大幅度增加,一般说来新生代占整个堆1/3比较合适
二、Survivor设置过小:导致对象从eden直接到达旧生代,降低了在新生代的存活时间,Survivor设置过大:导致eden过小,增加了GC频率
1). 吞吐量优先
JVM以吞吐量为指标,自行选择相应的GC策略及控制新生代与旧生代的大小比例,来达到吞吐量指标。这个值可由-XX:GCTimeRatio=n来设置
2). 暂停时间优先
JVM以暂停时间为指标,自行选择相应的GC策略及控制新生代与旧生代的大小比例,尽量保证每次GC造成的应用停止时间都在指定的数值范围内完成。这个值可由-XX:MaxGCPauseRatio=n来设置
优秀的调优指标:
1、MinorGC执行不到50ms
2、MinorGC不频繁,10s一次
3、FullGC不到1s
4、FullGC不低于10分钟1一次
调优方法:
一、-Xms -Xmx设置相同值,防止垃圾收集器最小最大之间收缩堆产生额外开销
二、年轻代、年老代(1:2)年轻代应用大量临时对象,持久对象年老代
三、年老代不占内存情况加大年轻代(1:1)
四、配置好机器,年老代选择并行收集算法:-XX+UseParalleloldGC
五、线程堆栈设置每个线程默认开户1Md堆栈存放栈帧变量,256k足够使用
常用调优参数
-Xms and -Xmx:指定JVM的初始和最大堆内存大小
-Xmn:设置年轻代大小
-Xss:设置每个线程的堆栈大小
-XX:+HeapDumpOnOutOfMemoryError and -XX:HeapDumpPath:让JVM在发生内存溢出时自动的生成堆内存快照
-XX:OnOutOfMemoryError:当内存溢发生时,执行指令,比如发个E-mail通知管理员或者执行一些清理工作
-XX:PermSize and -XX:MaxPermSize:设置永久代大小的初始值和最大值
-XX:PretenureSizeThreshold :令大于这个设置值的对象直接在老年代分配。
垃圾回收机制:
垃圾回收器:
1、新生代:serial 单线程 parNew 多线程 parllel seaverage 多线程 复制算法,吞吐量可控制
2、G1 并发,分代:
3、老年代:CMS 标记-清除算法,内存碎片 serial old 单线程 标记-整理算法 parllel old 多线程