JVM
一.JVM内存组成
1.1程序计数器:
属于线程私有,记录下一条要运行的指令
2.1java虚拟机栈:
线程的私有空间,和java线程同一时间创建,保存方法的局部变量、部分结果、参与方法的调用与返回
3.1本地方法栈:
类似于虚拟机栈
4.1堆:
回收过程:
1.当系统创建一个对象的时候,总是在Eden区操作,当这个区满了,那么就会触发一次YoungGC,也就是年轻代的垃圾回收。一般来说这时候不是所有的对象都没用了,所以就会把还能用的对象复制到From区。
2.这样整个Eden区就被清理干净了,可以继续创建新的对象,当Eden区再次被用完,就再触发一次YoungGC,然后呢,注意,这个时候跟刚才稍稍有点区别。这次触发YoungGC后,会将Eden区与From区还在被使用的对象复制到To区,
3.再下一次YoungGC的时候,则是将Eden区与To区中的还在被使用的对象复制到From区。
4.经过若干次YoungGC后,有些对象在From与To之间来回游荡,这时候From区与To区亮出了底线(阈值),这些家伙要是到现在还没挂掉,对不起,一起滚到(复制)老年代吧
老年代经过这么几次折腾,也就扛不住了(空间被用完),好,那就来次集体大扫除(Full GC),也就是全量回收。如果Full GC使用太频繁的话,无疑会对系统性能产生很大的影响。所以要合理设置年轻代与老年代的大小,尽量减少Full GC的操作。
GC日志打印解析:
1.GC日志打印信息:
-XX:+PrintGCTimeStamps输出格式:
289.556: [GC [PSYoungGen: 314113K->15937K(300928K)] 405513K->107901K(407680K), 0.0178568 secs] [Times: user=0.06 sys=0.00, real=0.01 secs]
293.271: [GC [PSYoungGen: 300865K->6577K(310720K)] 392829K->108873K(417472K), 0.0176464 secs] [Times: user=0.06 sys=0.00, real=0.01 secs]
详解:
293.271是从jvm启动直到垃圾收集发生所经历的时间,GC表示这是一次Minor GC(新生代垃圾收集);[PSYoungGen: 300865K->6577K(310720K)] 提供了新生代空间的信息,PSYoungGen,表示新生代使用的是多线程垃圾收集器Parallel Scavenge。300865K表示垃圾收集之前新生代占用空间,6577K表示垃圾收集之后新生代的空间。新生代又细分为一个Eden区和两个Survivor区,Minor GC之后Eden区为空,6577K就是Survivor占用的空间。
括号里的310720K表示整个年轻代的大小。
392829K->108873K(417472K),表示垃圾收集之前(392829K)与之后(108873K)Java堆的大小(总堆417472K,堆大小包括新生代和年老代)
由新生代和Java堆占用大小可以算出年老代占用空间,如,Java堆大小417472K,新生代大小310720K那么年老代占用空间是417472K-310720K=106752k;垃圾收集之前老年代占用的空间为392829K-300865K=91964k 垃圾收集之后老年代占用空间108873K-6577K=102296k.
0.0176464 secs表示垃圾收集过程所消耗的时间。
[Times: user=0.06 sys=0.00, real=0.01 secs] 提供cpu使用及时间消耗,user是用户模式垃圾收集消耗的cpu时间,实例中垃圾收集器消耗了0.06秒用户态cpu时间,sys是消耗系统态cpu时间,real是指垃圾收集器消耗的实际时间。
2.9.348: [GC 9.348: [DefNew: 13953K->976K(14400K), 0.0040943 secs]9.352: [Tenured: 32163K->32220K(32220K), 0.1182207 secs] 45514K->32338K(46620K), [Perm : 30467K->30467K(65536K)], 0.1224318 secs] [Times: user=0.12 sys=0.00, real=0.13 secs]
DefNew:表示新生代使用Serial串行GC垃圾收集器,defNew提供新生代空间信息;
Tenured:提供年老代空间信息;
45514K->32338K(46620K):整个堆空间大小信息;
Perm :提供持久代空间信息
5.1方法区
线程共享,存储类的元数据
二.JVM内存分配参数
2.1设置堆内存大小
1.-Xmx 指定堆的最大内存
运行:java –Xmx11M javatuning.ch5.memjory.TestXmx
获取可用的最大堆内存:Runtime.getRuntime().maxMemory()
2.-Xms 指定堆的最小内存
2.2设置新生代
-Xmn指定新生代大小一般设置整个堆内存的1/3-1/4
其值得大小对性能影响较大---增加GC、Full GC 对的消耗
2.3设置持久代
持久代的大小直接决定了系统可以支持多少个类定义和多少个常量,一般设置64M就可以满足大多数情况,最大可128M,若还不满足,则考虑系统优化
2.4设置线程栈
-Xss指定线程栈的大小
线程栈可以理解为系统内存的一部分,其和堆内存一样属于系统内存的组成部分,线程栈与堆内存指定内存均比较小有助于实现系统可以实现所能承受的最大线程数—大量线程并发
2.5堆的比例分配
总结
如下图:
三.垃圾收集基础
垃圾回收器处理的问题:
哪些对象需要被回收
何时回收这些对象
如何回收这些对象
3.1垃圾回收算法
3.1.1引用计数法
弊端:容易引起内存泄漏
3.1.2标记-清楚算法
思想:分为两个阶段,标记阶段和清除阶段,标记阶段是将标记所有的可达对象,清除阶段是将违背标记为可达对象的对象清除掉
弊端:清楚后空间变为不连续的空间,产生空间碎片
3.1.3复制算法
思想:将内存分为两块,每次只使用其中的一块,将其中一块中存活的对象复制到另外一块内存中,收集之后清除第一块内存,之后使用第二块内存,完成垃圾回收
优点:不会产生空间碎片,效率高
弊端:内存折半
适用于存活对象少,垃圾对象多的情况多用于新生代
3.1.4标记-压缩算法
思想:本质上是将标记-清楚算法进行优化,标记阶段先进行标记所有可达的对象,清除阶段先将可达对象压缩在内存的一侧,然后清理边界外的所有空间
优点:不会产生碎片空间
3.1.5分代算法
3.2垃圾回收器的分类
四.调优工具
4.1linux命令
4.1.1top命令
实时显示各个进程的占用情况
进程列表排序
M:根据驻留内存大小进行排序;
P:根据CPU使用百分比大小进行排序;
T:根据时间/累计时间进行排序;
4.2JDK命令
4.2.1jps命令
列出java进程pid和主函数名称
-m:输出传到主函数的参数
-l:输出主函数的完整路径
-v:输出传递给JVM的参数
4.2.2jstat