• ZGC现在只支持linux

Hotspot的参数分类

  • 标准参数:-开头,所有Hotspot都支持
  • 非标准参数:-X开头,特定版本Hotspot支持特定命令(参数)
  • 不稳定的参数:-XX开头,下个版本可能取消
  • 实验参数:好多是debug用的,一般我们用不上
  • java -version
  • java -X

内存会产生两种影响

  • 内存泄漏memory leak
  • 内存溢出out of memory
  • 内存泄漏不一定产生内存溢出
  • 两种常见的错误:
    • OOM:OutOfMemoryError
    • SOF:StackOverFlowError
  • 注意异常的类型是Error,不是Exception


Hotspot参数的使用

  • CMS的GC会更频繁!!!会有CMS详细的阶段过程(其实和PS+PO还是差不多的)
  • 没满会被回收吗

GC的日志格式

  • java - Xmn10M - Xms40M - Xmx60M - XX:+PrintCommandLineFlags - XX:+PrintGCDetails HelloGC

image.png

  • 日志会看起来很复杂,并且网上的信息也鱼龙混杂
  • linux中的time命令—->time ls
    • 表示用户态、内核态和总共的占用时间

image.png

  • 最复杂的是heapdump的部分
    • 当内存产生溢出之后,他会把整个堆给dump出来
    • 挺麻烦的,详细解释如下:
      • 一个eden加上from/to survivor中的一个是total,因为每次只能用一个(两个中的一个、其中之一)

高并发单机10k问题(这跟GC关系不大)

  • 举例子时突然想到的架构问题!!!
  • 目前已经被解决
  • redis是其中的关键
  • redis能撑住单机1w并发
  • 每秒100w的并发—->100台机器装100个redis理论上就可以搞定了
  • 任何一种架构也是和业务逻辑相关的,离了业务逻辑聊架构也是耍流氓
  • 不同的架构是不同的业务逻辑
  • 普通电商系统的业务逻辑:
    • 下单
    • 订单系统(IO)减库存
      • 先把这件货占住,不能等到货没有了,还给别人生成订单
    • 生成订单
    • 等待用户付款
  • 假如上述步骤是同步进行的,就是说等所有的步骤都完成了,即到了等待用户付款那一步才给用户反馈下单完成的信息,如果这算一个transaction的话(从逻辑上来说必须算一个transaction),非得按同步方式来运行,那么这个TPS撑不了几个,一秒钟几十个就可能会崩了
  • 12306可能的模型是异步进行的,下完单后,一个线程去减库存,另一个线程直接将你的下单信息直接扔到kafka或者redis中去,直接给用户返回异步的“ok,下单成功,等待付款”
  • 什么时候付完款了,订单处理线程就会去kafka或者redis中去拿数据,处理完一个就持久化一个,可以持久化到HBase中或者mysql中去
  • 还有一些细节!!!—-> 库存的信息存哪,可以就把库存信息放在一台机器上,要减库存的时候就去那台机器上去减,rpc的一个远程访问—->这样这一台机器的负载也会重了,压在一台机器上是不合理的、不靠谱的
  • 可以每台服务器留一部分票,就是说把票分下去
  • 大流量的处理方法:分而治之(大原则)
  • 1w张票,每台机器上放100张票,每个人只减自己的这部分库存
  • 存在数据倾斜的问题怎么办呢???
    • 即一台服务器很快没了,而另外的几台服务器还没少几张
    • 一台很快就没了,但是另外几台很多人都抢不着
    • 这时候还得有一台专门的服务器做他们之间的平衡(数据票的平衡)
    • 观察各台服务器的票数—->这一台没了,就从另一边调一点票过去!!!


命令的使用

  • 难在定位上而不是修正上!!!
  • jmap -histo ××× | head -20:其中的-histo参数不是history,而是histogram,表示分析的图形化界面(图表)
  • jmap的坑:线上系统,内存特别大,jmap执行期间会对进程产生很大影响,甚至卡顿(1个小时没有动,整个系统摊在那了)这里是指jmap -dump:format=b, file=XXX pid命令—->电商的系统不允许这么干
  • jmap -dump:format=b, file=XXX pid在内存特别大的时候线上进行分析会有很大影响,可能会造成系统摊在那儿;而jmap -histo ××× | head -20虽然对性能也有一些影响,但是相对来说是比较小的,还是可以去执行的,所以通过jmap -histo ××× | head -20就基本可以定位了
  • 实际中用jmap生成堆转储文件是不行的,但是可以获取类的信息;不能用转储这个命令—->不能用转储这个命令
  • 不能在线转储文件,但是可以在线定位!!!
  • 怎么解决:
    • 设定了参数HeapDump, OOM的时候会自动产生堆转储文件-XX:+HeapDumpOnOutOfMemoryError(不完善)
    • 很多服务器备份(高可用),停掉这台服务器对其他服务器不影响(不完善,但是可以说,是相对完善的一个说法,也不容易被面试官问出bug来)
    • 可以这么说“我知道jmap在内存很大的时候会很慢,所以我们一般进行jmap的话会先对这台服务器做一个隔离,隔离完之后再进行jmap分析”!!!可以使用jmap在线定位jmap -histo ××× | head -20—->查找有多少对象产主
    • 不能用jmap -dump:format=b, file=XXX pid
    • 🌟使用jmap在线定位jmap -histo ××× | head -20!!!
    • 在线定位:arthas在线排查!!!(用他来干)—->在线定位很困难,因此阿里做了很多工作(目前接触到的在线排查工具中最好用的,比国外的好用)(面试的时候说了麻烦???—->因为一般小点儿的公司用不到,说了容易露馅)—->尽量不要跟面试官说在线分析arthas,否则背调会比较严格
    • 阿里的arthas没有提供jmap的功能,还是离不了jmap -histo 这条命令
  • jmap可以手动导出堆转储文件,但线上内存特别大的时候一般不会这么干!!!

    1. jmap -dump:format=b, file=XXX pid
    2. java -Xms20M -Xmx20M -XX:+UseParallelGC -XX:+HeapDumpOnOutOfMemoryError com.mashibing.jvm.gc.T15_FullGC_Problem01
  • 使用MAT/jhat进行dump堆转储文件的分析—->参考—->MAT不是很好用,要用的话直接jvisualvm就可以了,纯命令行也可以用jhat

  • 找到代码的问题并优化代码
  • 一般的导出堆文件这件事jmap -dump:format=b, file=XXX pid在在线系统中不要轻易地这么干
  • 定位到代码后改代码,改不了代码就改小环境
  • 用图形界面在上线之前,甚至在上线地预运行期间或者内测期间,可以使用图形界面,正式上线之后用图形界面就比较少了
  • 上线之后如何观察、定位、处理出现地问题呢—->阿里的arthas

Arthas

反编译

  1. 查看动态代理生成类的问题
  2. 第三方库的问题(观察)
  3. 检查版本是否正确替换并生效—->版本检查!!!

热替换

  1. 类似热部署的概念
  2. 当前只可以更换方法的实现,方法的名称等要完全一样(不能改方法名和属性,参数?)
  3. 原理:用ClassLoader重新redefine,ClassLoader里面有一个方法叫redefine;调AppClassLoader的redefine方法重新加载类
  4. 与jar包无关,这些class都是从jar包中load到内存中的,jar是不会load到内存中去的
  5. 现在热替换还有一些限制!!!
  6. 改多个文件热替换,很多个方法、对象时,只能改方法实现—->改了方法名的话,其他用到的地方(调用的地方)也要进行相应的改变,就更加麻烦了,这是不行的
  7. 计划中后面的版本能换方法名

Arthas没有包含jmap的功能

  • jmap -histo就没有
  • 目前还不能完全替代jmap

OSGI也可以,监控JVM!!!

  • 但是OSGI比较复杂
  • 系统必须按照OSGI来构建才可以,可以很少有系统完全那么构建

trace

  • sc search class找到特定的class的相关信息等或者脚本啥的
  • watch 观察方法的**执行结果**!!!!