javaer面试必问:JVM调优

这是一个很广泛的问题,主要目标是使用较小的内存来获得较高的吞吐量或者较低的运行时延迟卡顿。落实到具体的话本人总结有以下措施(持续补充中…):

针对于内存的:

(1)选择合适的垃圾回收器。

由于堆的分代就是为了更好的管理内存,更方便回收内存,所以我们可以设置指定的垃圾回收器。在idea中VM Option参数加上下面的:

-XX:+UseSerialGC,虚拟机运行在Client模式下的默认值,Serial+Serial Old。
-XX:+UseParNewGC,ParNew+Serial Old,在JDK1.8被废弃,在JDK1.7还可以使用。
-XX:+UseConcMarkSweepGC,ParNew+CMS+Serial Old。
-XX:+UseParallelGC,虚拟机运行在Server模式下的默认值,Parallel Scavenge+Serial Old(PS Mark Sweep)。
-XX:+UseParallelOldGC,Parallel Scavenge+Parallel Old。
-XX:+UseG1GC,G1+G1。
在这里插入图片描述
关于常见垃圾收集器和回收算法,可以看:JVM垃圾收集子系统(七大垃圾收集器+垃圾收集算法+引用计数/可达性分析+finalize())
根据业务场景选择一些吞吐量优先或者停顿时间优先的,或者像G1这种控制停顿时间的基础上再有选择的进行回收的话,时间就要适当延长一丢丢,不然GC的频率会非常高,因为你指定的回收时间短,无法回收到指定大小内存。它被逼的只能提高GC的频率。

(2)合理分配内存大小

还是在idea那里我们可以临时调小运行时分配的内存,如果内存分配不合理,会导致Full GC ,GC一多,我们都知道就会卡顿,有运行时卡顿,就要调优。

Full GC (Ergonomics)  4071K->4071K(5120K), 0.0133345 secs]
[Full GC (Ergonomics)  4072K->4072K(5120K), 0.0139875 secs]
[Full GC (Ergonomics)  4074K->4074K(5120K), 0.0175359 secs]
[Full GC (Ergonomics)  4075K->4058K(5120K), 0.0184669 secs]
[Full GC (Ergonomics)  4074K->4027K(5120K), 0.0227864 secs]
[Full GC (Ergonomics)  4034K->4032K(5120K), 0.0163257 secs]
[Full GC (Ergonomics)  4034K->4033K(5120K), 0.0159485 secs]
[Full GC (Ergonomics)  4034K->4033K(5120K), 0.0121078 secs]
[Full GC (Ergonomics)  4034K->4033K(5120K), 0.0149764 secs]
[Full GC (Ergonomics)  4034K->3966K(5120K), 0.0177060 secs]
[Full GC (Ergonomics)  3992K->3966K(5120K), 0.0176927 secs]
[Full GC (Ergonomics)  3992K->3970K(5120K), 0.0166102 secs]
[Full GC (Ergonomics)  3992K->3894K(5120K), 0.0252081 secs]
[Full GC (Ergonomics)  3977K->3895K(5120K), 0.0229713 secs]
[GC (Allocation Failure) -- 3977K->4089K(5120K), 0.0031258 secs]
[Full GC (Ergonomics)  4089K->3067K(5120K), 0.0323390 secs]
[Full GC (Ergonomics)  4091K->3989K(5120K), 0.0282569 secs]
[Full GC (Ergonomics)  4080K->3942K(5120K), 0.0143164 secs]
[Full GC (Ergonomics)  4086K->3934K(5120K), 0.0185123 secs]

编码方面:

(1)大对象会直接进入老年带,尽量都使用单例模式进行创建。减少老年带发生GC的频率。Spring帮我们做的IOC就非常有帮助。
(2)万恶之源!不要手动 System.GC() ;这个由不得我们控制也最好不要控制。因为这样显示声明的GC,不GC则已,一GC就Full GC .
(3)严防内存泄漏!例如使用线程池,任务队列的时候,要深入理解各种参数和底层原理,严防死守内存泄漏!
(4)最大线程数要有规范,线程底层通过LWP轻量级进程进行进程间的调度,充分使用了多核CPU,但是无限制开启线程会OOM和徒增无谓的线程加锁和切换开销。
(5)栈帧一个个方法之间传递数据,如果能使用标量替换,就不要传递对象内存引用,比如一个大对象只需要它一个int id,你就不要把整个对象new出来再传引用。把大对象的作用域局限在方法内,可以进行栈上分配。省了GC的功夫的同时还省去了同步锁。JVM中逃逸分析和标量替换和栈上分配和同步消除

工具使用:

强烈推荐阿里巴巴的Arthas~
在另外一篇博客:Java系统性能监控工具Arthas的使用
在这里插入图片描述

以上就是个人基于经验的一些总结,持续会有补充,欢迎反驳留言~

猜你喜欢

转载自blog.csdn.net/whiteBearClimb/article/details/108768975