Java因其开源、高效、跨平台、生态好的特性使得它成为当前主流的编程开发语言,即使之前使用其它技术栈的公司现在也慢慢向Java平台迁移。相信很多Java同学在面试时都会被问到JVM调优之类的问题,但似乎感觉日常工作中又很少进行JVM调优,那对于一般的Java项目到底要不要进行JVM调优呢?什么是JVM调优? 在说JVM调优前,我们得先说说JVM。什么是JVM呢?JVM其实是Java虚拟机(Java Virtual Machine)的简称,Java之所以能跨平台,其实靠的就是JVM。 JVM它是一个虚拟机,虽然JVM本身上是一个计算机程序,但它也有自己的一整套软硬件环境。 就好比你新买来了一台电脑,装好了系统后,你能正常使用电脑了。但很多用户是需要对电脑进行一些定制化设置的,比如桌面背景等。同样,JVM在安装后,即使不进行任何额外设置也能正常工作,但在某些场景下同样需要对JVM进行一些调优,而调优的手段就是更改JVM参数。JVM调优的目的及调优项 1、JVM调优的目的 JVM调优的目的就是:尽可能使用较小的内存和CPU来让Java程序获得更高的吞吐量及较低的延迟。 2、JVM常见调优项 JVM最为常见的调优就是更改JVM默认的参数,比如: 初始堆大小:-Xms 最大堆大小:-Xmx 新生代大小:-Xmn 永生代最小值:-XX:PermSize 永生代最大值:-XX:MaxPermSize一般项目到底要不要进行JVM调优? 其实JVM默认的设置是能满足常规项目需要的,看上去JVM调优只要改改参数什么的很简单,其实并非我们所想的那么简单。 JVM调优如果调整得不好反而会影响整个项目的稳定,正常情况下不建议大家对JVM进行调优,除非你的Java项目内存占用过高而你的服务器内存过低时。 下载下来的jvm已经调试好了,除非无法满足使用需求,否则不要轻易修改 一般的项目肯定是不需要的。其实 JVM 调优的可操作的空间很小,绝大部分时候我们也仅仅只用到几个内存设置参数,设法降低 Full GC 频率,实际上调整 JVM 带来不了多少性能提升。程序性能不佳,撑不住业务,往往问题出在程序本身,很多时候都是程序中有大列表或者创建对象频率过高,导致内存增长过快频繁Full GC,CPU因为Full GC跑满。 首先,直接答复一次题主的问题,一般项目肯定是不需要进行JVM调优的,因为JVM 本身就是为这种低延时、高并发、大吞吐的服务设计和优化的,我们很少需要去改变什么。所以,我们往往更偏重于应用服务本身的调优。 在一些应用中,比如大数据计算引擎,是一种非常极端的JVM应用,对延时的要求并不高,但对吞吐量要求很高,会有大量的短生命周期对象产生,同时也有大量的对象生存时间非常久,我们就需要对特定的一些 JVM 参数进行修改,不断调整,做到最优。 再比如生产环境中出现内存溢出,我们需要判断是由于大峰值下没有限流,瞬间创建大量对象而导致的内存溢出,还是是由于内存泄漏而导致的内存溢出。对于内存泄漏导致的,这种问题就是程序的 Bug,我们需要及时找到问题代码进行修改,而不是调整 JVM。 如果要调优,需要有参考指标,不要为了调优而调优,要有一个目标参考值,最终要达到什么样的调优结果,没有指标的调优都是瞎指挥!以下列出几个衡量系统性能的常用指标:响应时间:响应时间是衡量系统性能的重要指标之一,响应时间越短,性能越好,一般一个接口的响应时间是在毫秒级。响应时间还包括数据库响应时间、服务端响应时间、网络响应时间、客户端响应时间。TPS:指系统接口的 TPS(每秒事务处理量),因为 TPS 体现了接口的性能,TPS 越大,性能越好。在系统中,吞吐量分为两种:磁盘吞吐量和网络吞吐量。计算机资源分配使用率:通常由 CPU 占用率、内存使用率、磁盘 I/O、网络 I/O 来表示资源使用率。这几个参数好比一个木桶,如果其中任何一块木板出现短板,任何一项分配不合理,对整个系统性能的影响都是毁灭性的。 对于JVM调优来说,主要关注以下两方面:JVM内存空间分配参数设置和垃圾回收器的选择。内存空间的分配设置:JVM 内存分配不合理带来的性能表现并不会像内存溢出问题这么突出,最直接的表现就是频繁的 GC,这会导致上下文切换等性能问题,从而降低系统的吞吐量、增加系统的响应时间。具体的实现包括调整堆内存空间减少 Full GC、调整年轻代减少 MinorGC、设置合理的 Eden 和 Survivor 区的比例。选择合适的垃圾回收器:垃圾回收主要是指堆和方法区的回收,堆中的回收主要是对象的回收,方法区的回收主要是废弃常量和无用的类的回收。垃圾收集器的种类很多,不同的场景有不同的选择。对于每次操作的响应时间要求比较高的,我们可以选择响应速度较快的 GC回收器,比如 CMS 回收器和 G1 回收器;而对系统吞吐量有较高要求时,就可以选择 Parallel Scavenge 回收器来提高系统的吞吐量。 对于还在正常运 的系统: 1. 可以使 jmap来查看JVM中各个区域的使 情况 2. 可以通过jstack来查看线程的运 情况, 如哪些线程阻塞、是否出现了死锁 3. 可以通过jstat命令来查看垃圾回收的情况,特别是fullgc,如果发现fullgc 较频繁,那么就得进 调优了 4. 通过各个命令的结果,或者jvisualvm等 具来进 分析 5. 先,初步猜测频繁发送fullgc的原因,如果频繁发 fullgc但是 直没有出现内存溢出,那么表示fullgc实际上是回收了很多对象了,所以这些对象最好能在younggc过程中就直接回收掉,避免这些对象进 到 年代,对于这种情况,就要考虑这些存活时间不 的对象是不是 较 ,导致年轻代放不下,直接进 到了 年代,尝试加 年轻代的 ,如果改完之后,fullgc减少,则证明修改有效 6. 同时,还可以找到占 CPU最多的线程,定位到具体的 法,优化这个 法的执 ,看是否能避免某些对象的创建,从 节省内存 阿里、京东、蚂蚁等大厂面试真题解析对于已经发 了OOM的系统: 1. 般 产系统中都会设置当系统发 了OOM时, 成当时的dump 件(-XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/usr/local/base) 2. 我们可以利 jsisualvm等 具来分析dump 件 3. 根据dump 件找到异常的实例对象,和异常的线程(占 CPU ),定位到具体的代码 4. 然后再进 详细的分析和调试 总之,调优不是 蹴 就的,需要分析、推理、实践、总结、再分析,最终定位到具体的问题 F:softJavajdk1.8bin>jcmd -hUsage: jcmd or: jcmd -lor: jcmd -hcommand must be a valid jcmd command for the selected jvm.Use the command "help" to see which commands are available.If the pid is 0, commands will be sent to all Java processes.The main class argument will be used to match (either partiallyor fully) the class used to start Java.If no options are given, lists Java processes (same as -p).PerfCounter.print display the counters exposed by this process-f read and execute commands from the file-l list JVM processes on the local machine-h this help ------------- 如果我回答对你有帮助,请关注我一下。或有其他问题也可以关注我,给我发私信 一般项目还真不用,随便配置个1G的堆内存够用,除非遇到oom问题或者效率实在有问题而其他方面已经优化。