精华内容
下载资源
问答
  • JVM调优

    2019-09-26 16:23:14
  • 文章目录参考JVM 调优指标JVM 日志JVM 调优工具 参考 https://blog.csdn.net/weixin_42447959/article/details/81637909 JVM 调优指标 内存占用:程序正常运行需要的内存大小。 延迟:由于垃圾收集而引起的程序停顿...

    参考

    https://blog.csdn.net/weixin_42447959/article/details/81637909

    JVM 调优指标

    • 内存占用:程序正常运行需要的内存大小。
    • 延迟:由于垃圾收集而引起的程序停顿时间。
    • 吞吐量:用户程序运行时间占用户程序和垃圾收集占用总时间的比值。

    JVM 日志

    调优可以依赖、参考的数据有系统运行日志、堆栈错误信息、gc日志、线程快照、堆转储快照等。

    • 系统运行日志:在程序代码中打印出的日志,即 logger 出的日志,描述了代码级别的系统运行轨迹(执行的方法、入参、返回值等)

    • 堆栈错误信息:当系统出现异常后,可以根据堆栈信息初步定位问题所在

    • GC日志:程序启动时用 -XX:+PrintGCDetails 和 -Xloggc:/data/jvm/gc.log 可以在程序运行时把gc的详细过程记录下来,或者直接配置“-verbose:gc”参数把gc日志打印到控制台

    • 线程快照:查看线程在某一时刻的状态,当系统中可能存在请求超时、死循环、死锁等情况时,可以根据线程快照来进一步确定问题。通过执行虚拟机自带的“ jstack pid ”命令,可以 dump 出当前进程中线程的快照信息,

    • 堆转储快照:程序启动时可以使用 “-XX:+HeapDumpOnOutOfMemory” 和 “-XX:HeapDumpPath=/data/jvm/dumpfile.hprof”,当程序发生内存溢出时,把当时的内存快照以文件形式进行转储(也可以直接用 jmap 命令转储程序运行时任意时刻的内存快照)

    JVM 调优工具

    • jps(JVM process Status):查看虚拟机启动的所有进程、执行主类的全名、JVM启动参数

    • jstat(JVM Statistics Monitoring Tool):监视虚拟机信息,Java堆状况(各个区的容量、使用容量、gc时间等信息)

    • jmap(Memory Map for Java):查看堆内存信息 、每个类的实例数量和内存占用。jmap -dump 可以转储堆内存快照到指定文件

    • jconsole、jvisualvm:分析内存信息(各个区如Eden、Survivor、Old等内存变化情况)、线程数、类加载数和CPU占用率、GC情况、每个线程的堆栈信息、检测死锁、JVM参数

    • jhat(JVM Heap Analysis Tool) :分析内存快照

    展开全文
  • 来源:https://www.iteye.com/blog/pengjiaheng-5524561 JVM调优工具Jconsole,jProfile,VisualVM。Jconsole: jdk自带,功能简单,但是可以在系统有一定负荷的情况下使用。对垃圾回收算法有很详细的跟踪。JProfiler...
    2e36cdf40164bb41e9d55e4a069fd4fe.gif

    f13a6fe59bce89365be3c849feb63953.png

    来源:https://www.iteye.com/blog/pengjiaheng-552456

    1

    JVM调优工具 

    Jconsole,jProfile,VisualVM。

    Jconsole : jdk自带,功能简单,但是可以在系统有一定负荷的情况下使用。对垃圾回收算法有很详细的跟踪。

    JProfiler:商业软件,需要付费。功能强大。

    VisualVM:JDK自带,功能强大,与JProfiler类似。推荐。

    2
     如何调优 

    观察内存释放情况、集合类检查、对象树。

    上面这些调优工具都提供了强大的功能,但是总的来说一般分为以下几类功能。

    堆信息查看

    fcb1c25723de380319d7ab92a872a2f1.png

    可查看堆空间大小分配(年轻代、年老代、持久代分配)

    提供即时的垃圾回收功能

    垃圾监控(长时间监控回收情况)

    9a7d4a4f2dccef8d59da136aa8d899b6.png

    查看堆内类、对象信息查看:数量、类型等

    9a1791e11eba148e6b75ee63738ef50e.png

    对象引用情况查看

    有了堆信息查看方面的功能,我们一般可以顺利解决以下问题:

      --年老代年轻代大小划分是否合理

      --内存泄漏

      --垃圾回收算法设置是否合理

    3
     线程监控 

    5be2e0cc44be52ad8b62077fdfd9cc44.png

    线程信息监控:系统线程数量。

    线程状态监控:各个线程都处在什么样的状态下

    9d79b128b00f017d0a1d7d4dfe1c0e57.png

    Dump线程详细信息:查看线程内部运行情况

    死锁检查

    1、热点分析

    075a3cbb7ddebde84c8120d7266fc36d.png 

    CPU热点:检查系统哪些方法占用的大量CPU时间

    内存热点:检查哪些对象在系统中数量最大(一定时间内存活对象和销毁对象一起统计)

    这两个东西对于系统优化很有帮助。我们可以根据找到的热点,有针对性的进行系统的瓶颈查找和进行系统优化,而不是漫无目的的进行所有代码的优化。

    2、快照

    快照是系统运行到某一时刻的一个定格。在我们进行调优的时候,不可能用眼睛去跟踪所有系统变化,依赖快照功能,我们就可以进行系统两个不同运行时刻,对象(或类、线程等)的不同,以便快速找到问题。

    举例说,我要检查系统进行垃圾回收以后,是否还有该收回的对象被遗漏下来的了。那么,我可以在进行垃圾回收前后,分别进行一次堆情况的快照,然后对比两次快照的对象情况。

    4
     内存泄漏检查 

    内存泄漏是比较常见的问题,而且解决方法也比较通用,这里可以重点说一下,而线程、热点方面的问题则是具体问题具体分析了。

    内存泄漏一般可以理解为系统资源(各方面的资源,堆、栈、线程等)在错误使用的情况下,导致使用完毕的资源无法回收(或没有回收),从而导致新的资源分配请求无法完成,引起系统错误。

    内存泄漏对系统危害比较大,因为他可以直接导致系统的崩溃。

    需要区别一下,内存泄漏和系统超负荷两者是有区别的,虽然可能导致的最终结果是一样的。内存泄漏是用完的资源没有回收引起错误,而系统超负荷则是系统确实没有那么多资源可以分配了(其他的资源都在使用)。

    1、年老代堆空间被占满

    异常:java.lang.OutOfMemoryError: Java heap space

    说明:这是最典型的内存泄漏方式,简单说就是所有堆空间都被无法回收的垃圾对象占满,虚拟机无法再在分配新空间。

    df6ef9ef3fd259631ed4507b0fb29157.png

    如上图所示,这是非常典型的内存泄漏的垃圾回收情况图。所有峰值部分都是一次垃圾回收点,所有谷底部分表示是一次垃圾回收后剩余的内存。连接所有谷底的点,可以发现一条由底到高的线,这说明,随时间的推移,系统的堆空间被不断占满,最终会占满整个堆空间。因此可以初步认为系统内部可能有内存泄漏。(上面的图仅供示例,在实际情况下收集数据的时间需要更长,比如几个小时或者几天)

    解决方法:这种方式解决起来也比较容易,一般就是根据垃圾回收前后情况对比,同时根据对象引用情况(常见的集合对象引用)分析,基本都可以找到泄漏点。

    2、持久代被占满

    异常:java.lang.OutOfMemoryError: PermGen space

    说明:Perm空间被占满。无法为新的class分配存储空间而引发的异常。这个异常以前是没有的,但是在Java反射大量使用的今天这个异常比较常见了。主要原因就是大量动态反射生成的类不断被加载,最终导致Perm区被占满。

    更可怕的是,不同的classLoader即便使用了相同的类,但是都会对其进行加载,相当于同一个东西,如果有N个classLoader那么他将会被加载N次。因此,某些情况下,这个问题基本视为无解。当然,存在大量classLoader和大量反射类的情况其实也不多。

    解决方法

      -XX:MaxPermSize=16m

      换用JDK。比如JRocket。

    3、堆栈溢出

    异常:java.lang.StackOverflowError

    说明:这个就不多说了,一般就是递归没返回,或者循环调用造成

    4、线程堆栈满

    异常:Fatal: Stack size too small

    说明:java中一个线程的空间大小是有限制的。JDK5.0以后这个值是1M。与这个线程相关的数据将会保存在其中。但是当线程空间满了以后,将会出现上面异常。

    解决方法:增加线程栈大小。-Xss2m。但这个配置无法解决根本问题,还要看代码部分是否有造成泄漏的部分。

    5、系统内存被占满

    异常:java.lang.OutOfMemoryError: unable to create new native thread

    说明:这个异常是由于操作系统没有足够的资源来产生这个线程造成的。系统创建线程时,除了要在Java堆中分配内存外,操作系统本身也需要分配资源来创建线程。因此,当线程数量大到一定程度以后,堆中或许还有空间,但是操作系统分配不出资源来了,就出现这个异常了。

    分配给Java虚拟机的内存愈多,系统剩余的资源就越少,因此,当系统内存固定时,分配给Java虚拟机的内存越多,那么,系统总共能够产生的线程也就越少,两者成反比的关系。同时,可以通过修改-Xss来减少分配给单个线程的空间,也可以增加系统总共内生产的线程数。

    解决:

        1. 重新设计系统减少线程数量。

        2. 线程数量不能减少的情况下,通过-Xss减小单个线程大小。以便能生产更多的线程。

    历史推荐

    1、JVM调优:基本概念2、JVM调优:基本垃圾回收算法3、JVM调优 垃圾回收面临的问题4、JVM调优 分代垃圾回收详述5、JVM调优 典型配置6、JVM调优:新一代的垃圾回收算法4d66d3f0b9354f2ef8294241529368f7.png

    公众号ID|javabaiwen

    小编微信|646448081

    每天分享技术干货

    视频 | 电子书 | 面试题 | 开发经验

    展开全文
  • jvm调优思路2. 订单的秒杀模块jvm调优案例 1. jvm调优思路         jvm调优其实更多的是对GC的优化,尤其是尽量减少full GC。       &...


    1. jvm调优思路

            jvm调优其实更多的是对GC的优化,尤其是尽量减少full GC。

            大多数情况下,对象在Eden区分配,当Eden区没有足够空间进行分配时,虚拟机将进行一次Minor GC ,可能有99%的对象被标记为垃圾被回收,剩余存活的对象会进入为空的survivor,下一次Eden区满了之后,又会触发minor gc,把Eden区和survivor区垃圾对象回收,把剩余存活的对象一次性挪动到另外一块为空的to区,因为新生代的对象都是朝生夕死的,存活时间很短,所以JVM默认的8:1:1的比例是很合适的,让eden区尽量的大,survivor区够用即可。

    Minor GC/Young GC:指发生新生代的的垃圾收集动作,Minor GC非常频繁,回收速度一般也比较快。
    Major GC/Full GC:一般会回收老年代 ,年轻代,方法区的垃圾,Major GC的速度一般会比Minor GC的慢 10倍以上。
    Eden与Survivor区默认8:1:1

    明白了上边的对象流转过程,我们可以在这个过程中做一些手脚,来进行jvm调优!


    1.1 jvm调优方案

    ①:设置大对象直接进入老年代! 大对象就是需要大量内存空间的对象(比如数组、字符串) ,通过jvm参数-XX:PretenureSizeThreshold 可以设置大对象的大小,如果对象超过设置大小会直接进入老年代,不会进入年轻代,这个参数只在 Serial 和ParNew两个收集器下有效。

    具体操作:-XX:PretenureSizeThreshold=1000000 (单位是字节) -XX:+UseSerialGC

    使用场景:当我们可以确定系统中的对象大部分为大对象,且短期内不会被垃圾回收,就可以根据对象大小设置jvm参数,让这些大对象直接进入老年代,省去了对象在新生代流转的过程,节省了Eden区的空间,因为大对象最终总会进入老年代的,还不如提前让出Eden空间,让他处理更多的小对象,提升系统性能!

    ②:设置长期存活的对象提前进入老年代! 新生代的对象每熬过一次Minor GC ,其年龄就会+1,默认15岁,也就是流转15次就会进入老年代。当我们的系统中大概有大部分(80%)的对象都会经过15次Minor GC 进入老年代,我们可以通过设置-XX:MaxTenuringThreshold来调整进入老年代需要的年龄阈值。比如设置年龄为8即可进入老年代,这样那些长期存活的对象,就可以尽早的进入老年代,减少对象在新生代的流转次数,提升了系统性能!

    ③:根据survivor区的动态年龄判断机制,合理设置新生代大小 。一般超过survivor区大小的60%会发生动态年龄判断机制,此时把最老的对象放进老年代。可以适当增加survivor区的大小避免Full GC!动态年龄判断的机制作用其实是希望那些可能是长期存活的对象,尽早进入老年代,避免多次复制操作而降低效率。


    2. 订单的秒杀模块jvm调优案例

    架构如下:

    对亿级电商平台的调优中,首先要对自己的系统有足够的了解。根据以上架构:
    ①:如果平台日活用户为500w,那大部分的付费转化率为10%,也就是每日50w单左右。

    ②:如果50w单是在平时非促销的时候,下订单操作通过负载均衡打到服务器上,也就每秒几单、十几单的样子,服务器可以抗住。但如果要搞促销,50w单要在几分钟内产生,那么每秒钟就高达1000多单的交易,如果不合理设置jvm参数,就可能会频繁发生Full GC!

    ③:假设有订单三台服务器,每秒1000单通过负载均衡到三台服务器,每台服务器每秒处理300单左右!假设每个订单对象1kb,每秒300kb对象生成,订单接口中肯定不止一个订单对象,还有库存、优惠券、积分等对象,所以300kb放大20倍,也就是6MB,同时还可能有别的操作,比如订单查询等,再放大10倍,也就是60MB,因为要保证请求速度,所以这60MB对象1s后都会成为垃圾。

    ④:此时每秒60M对象进入堆内存。假如服务器内存是8G,给操作系统分配4-5G,剩下的分给JVM,因为 新生代:老年代 = 1:2,则新生代拿到1G,老年代2G,元空间512Mb,栈1M,jvm参数设置 如图所示!对象会首先进入Eden,800/60 ≈ 14秒 ,也即14秒后Eden区被放满,发生Minor GC!

    在这里插入图片描述
    ⑤:由于不到14秒,Eden区就被占满,所以到13秒时就可能会发生Minor GC,进行stw,而此时第14秒创建的对象被stw,GC完毕后,第14秒创建的对象接着执行,此时的对象会进入survivor区。由于survivor区存在动态年龄判断机制,对象大小>50MB,此时大于1岁的对象会直接进入老年代。也就是每14秒60M对象进入老年代!导致几分钟一次GC!

    ⑥:由于上述原因就是由survivor区存在动态年龄判断机制导致的,所以我们可以通过调整新生代大小来避免,对象进入老年代!
    在这里插入图片描述
    把年轻代分配2G,则survivor区为200M,60M的对象进来不至于触发动态年龄判断机制,一次Minor GC就杀死了所有对象,几乎没有对象进入老年代,解决了Fulle GC频繁的问题!

    结论:通过上面这些内容介绍,大家应该对JVM优化有些概念了,就是尽可能让对象都在新生代里分配和回收,尽量别让太多对象频繁进入老年代,避免频繁对老年代进行垃圾回收,同时给系统充足的内存大小,避免新生代频繁的进行垃圾回收。

    展开全文
  • JVM 调优

    2020-12-23 19:09:50
    题记-------JVM 调优分类及思路: 调优是一个很大的概念,简单说就是把系统进行优化,但是站在一个系统的角度,能够干的事情太多了,一般调优的思路可以是“测试 - 分析 - 调优”三步走。任何调优一般都需要结合场景...
  • 深入浅出JVM调优,看完你就懂

    万次阅读 多人点赞 2019-08-12 13:50:52
    深入浅出JVM调优 基本概念: JVM把内存区分为堆区(heap)、栈区(stack)和方法区(method)。由于本文主要讲解JVM调优,因此我们可以简单的理解为,JVM中的堆区中存放的是实际的对象,是需要被GC的。其他的都无需GC。 ...
  • jvm调优

    千次阅读 2019-07-02 22:20:53
    JVM调优设计哪几方面: 合理的编写程序 充分并合理的使用硬件资源 合理的进行JVM调优 需要关注的点: 1. 非堆内存: 堆外内存 文件句柄 Socket句柄 数据库连接 2. 文件: 限制文件大小,最好采用异步方式(写...
  • jvm 调优

    2019-09-18 11:35:13
    -Xms1024m -Xmx1024m -XX:+PrintGCDetails jvm 调优

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 17,944
精华内容 7,177
关键字:

jvm调优