五、GC分析&内存调优

  • Post author:
  • Post category:其他




(持续更新中… …)



GC分析&内存调优



工具篇



JDK自带的工具



jconsole



jvisualvm



第三方工具



arthas(重要)



jprofiler(收费的)



MAT、GChisto、gcviewer、GC Easy(待完善)



参数、命令

1、JVM的命令行参数参考:

https://docs.oracle.com/javase/8/docs/technotes/tools/unix/java.html


2、HotSpot参数分类

标准: – 开头,所有的HotSpot都支持

非标准:-X 开头,特定版本HotSpot支持特定命令

不稳定:-XX 开头,下个版本可能取消

试验用程序:

import java.util.List;
import java.util.LinkedList;

public class HelloGC {
  public static void main(String[] args) {
    System.out.println("HelloGC!");
    List list = new LinkedList();
    for(;;) {
      byte[] b = new byte[1024*1024];
      list.add(b);
    }
  }
}

区分概念:内存泄漏memory leak,内存溢出out of memory

java -XX:+PrintCommandLineFlags HelloGC

java -Xmn10M -Xms40M -Xmx60M -XX:+PrintCommandLineFlags -XX:+PrintGC HelloGCPrintGCDetails PrintGCTimeStamps PrintGCCauses

java -XX:+UseConcMarkSweepGC -XX:+PrintCommandLineFlags HelloGC

java -XX:+PrintFlagsInitial 默认参数值

java -XX:+PrintFlagsFinal 最终参数值

java -XX:+PrintFlagsFinal | grep xxx 找到对应的参数

java -XX:+PrintFlagsFinal -version |grep GC



常见垃圾回收器组合参数设定:(1.8)

  • -XX:+UseSerialGC = Serial New (DefNew) + Serial Old

    小型程序。默认情况下不会是这种选项,HotSpot会根据计算及配置和JDK版本自动选择收集器

  • -XX:+UseParNewGC = ParNew + SerialOld

    这个组合已经很少用(在某些版本中已经废弃)

    https://stackoverflow.com/questions/34962257/why-remove-support-for-parnewserialold-anddefnewcms-in-the-future

  • -XX:+UseConc(urrent)MarkSweepGC = ParNew + CMS + Serial Old

  • -XX:+UseParallelGC = Parallel Scavenge + Parallel Old (1.8默认) 【PS + SerialOld】

  • -XX:+UseParallelOldGC = Parallel Scavenge + Parallel Old

  • -XX:+UseG1GC = G1

  • Linux中没找到默认GC的查看方法,而windows中会打印UseParallelGC

    • java +XX:+PrintCommandLineFlags -version
    • 通过GC的日志来分辨
  • Linux下1.8版本默认的垃圾回收器到底是什么?

    • 1.8.0_181 默认(看不出来)Copy MarkCompact
    • 1.8.0_222 默认 PS + PO



GC常用参数

-Xmn -Xms -Xmx -Xss年轻代 最小堆 最大堆 栈空间

-XX:+UseTLAB使用TLAB,默认打开

-XX:+PrintTLAB打印TLAB的使用情况

-XX:TLABSize设置TLAB大小

-XX:+DisableExplictGCSystem.gc()不管用 ,FGC

-XX:+PrintGC

-XX:+PrintGCDetails

-XX:+PrintHeapAtGC

-XX:+PrintGCTimeStamps

-XX:+PrintGCApplicationConcurrentTime (低)打印应用程序时间

-XX:+PrintGCApplicationStoppedTime (低)打印暂停时长

-XX:+PrintReferenceGC (重要性低)记录回收了多少种不同引用类型的引用

-verbose:class类加载详细过程

-XX:+PrintVMOptions

-XX:+PrintFlagsFinal -XX:+PrintFlagsInitial必须会用

-Xloggc:opt/log/gc.log

-XX:MaxTenuringThreshold升代年龄,最大值15

锁自旋次数 -XX:PreBlockSpin 热点代码检测参数-XX:CompileThreshold 逃逸分析 标量替换 … 这些不建议设置



Parallel常用参数

-XX:SurvivorRatio

-XX:PreTenureSizeThreshold大对象到底多大

-XX:MaxTenuringThreshold

-XX:+ParallelGCThreads并行收集器的线程数,同样适用于CMS,一般设为和CPU核数相同

-XX:+UseAdaptiveSizePolicy自动选择各区大小比例



CMS常用参数

-XX:+UseConcMarkSweepGC

-XX:ParallelCMSThreadsCMS线程数量

-XX:CMSInitiatingOccupancyFraction使用多少比例的老年代后开始CMS收集,默认是68%(近似值),如果频繁发生SerialOld卡顿,应该调小,(频繁CMS回收)

-XX:+UseCMSCompactAtFullCollection在FGC时进行压缩

-XX:CMSFullGCsBeforeCompaction多少次FGC之后进行压缩

-XX:+CMSClassUnloadingEnabled

-XX:CMSInitiatingPermOccupancyFraction达到什么比例时进行Perm回收

GCTimeRatio设置GC时间占用程序运行时间的百分比

-XX:MaxGCPauseMillis停顿时间,是一个建议时间,GC会尝试用各种手段达到这个时间,比如减小年轻代



G1常用参数

-XX:+UseG1GC

-XX:MaxGCPauseMillis建议值,G1会尝试调整Young区的块数来达到这个值

-XX:GCPauseIntervalMillis?GC的间隔时间

-XX:+G1HeapRegionSize分区大小,建议逐渐增大该值,1 2 4 8 16 32。随着size增加,垃圾的存活时间更长,GC间隔更长,但每次GC的时间也会更长ZGC做了改进(动态区块大小)

G1NewSizePercent新生代最小比例,默认为5%

G1MaxNewSizePercent新生代最大比例,默认为60%

GCTimeRatioGC时间建议比例,G1会根据这个值调整堆空间

ConcGCThreads线程数量

InitiatingHeapOccupancyPercent启动G1的堆空间占用比例



调优案例



案例1-微笑大佬的案例

http://www.ityouknow.com/jvm/2017/09/19/GC-tuning.html



案例2-马士兵的案例



调优前的基础概念

  1. 吞吐量:用户代码时间 /(用户代码执行时间 + 垃圾回收时间)
  2. 响应时间:STW越短,响应时间越好

    所谓调优,首先确定,追求啥?吞吐量优先,还是响应时间优先?还是在满足一定的响应时间的情况下,要求达到多大的吞吐量…

    问题:科学计算,吞吐量。数据挖掘,thrput。吞吐量优先的一般:(PS + PO)。响应时间:网站 GUI API (1.8 G1)



什么是调优

  1. 根据需求进行JVM规划和预调优
  2. 优化运行JVM运行环境(慢,卡顿)
  3. 解决JVM运行过程中出现的各种问题(OOM)



调优,从规划开始

调优,从业务场景开始,没有业务场景的调优都是耍流氓。

无监控(压力测试,能看到结果),不调优。

步骤:

1、熟悉业务场景(没有最好的垃圾回收器,只有最合适的垃圾回收器)

1.1、响应时间、停顿时间 [CMS G1 ZGC] (需要给用户作响应)

1.2、吞吐量 = 用户时间 /( 用户时间 + GC时间) [PS]

2、选择回收器组合。3、计算内存需求(经验值 1.5G 16G)。4、选定CPU(越高越好)5、设定年代大小、升级年龄。6、设定日志参数。6.1 -Xloggc:/opt/xxx/logs/xxx-xxx-gc-%t.log -XX:+UseGCLogFileRotation -XX:NumberOfGCLogFiles=5 -XX:GCLogFileSize=20M -XX:+PrintGCDetails -XX:+PrintGCDateStamps -XX:+PrintGCCause。6.2或者每天产生一个日志文件

7、观察日志情况。

案例1

垂直电商,最高每日百万订单,处理订单系统需要什么样的服务器配置?

这个问题比较业余,因为很多不同的服务器配置都能支撑(1.5G 16G)1小时360000集中时间段, 100个订单/秒,(找一小时内的高峰期,1000订单/秒)经验值,非要计算:一个订单产生需要多少内存?512K * 1000 500M内存专业一点儿问法:要求响应时间100ms压测!

案例2

12306遭遇春节大规模抢票应该如何支撑?12306应该是中国并发量最大的秒杀网站:号称并发量100W最高CDN -> LVS -> NGINX -> 业务系统 -> 每台机器1W并发(10K问题) 100台机器普通电商订单 -> 下单 ->订单系统(IO)减库存 ->等待用户付款12306的一种可能的模型: 下单 -> 减库存 和 订单(redis kafka) 同时异步进行 ->等付款减库存最后还会把压力压到一台服务器可以做分布式本地库存 + 单独服务器做库存均衡大流量的处理方法:分而治之

案例3

怎么得到一个事务会消耗多少内存?

弄台机器,看能承受多少TPS?是不是达到目标?扩容或调优,让它达到。

用压测来确定。



优化环境

  1. 有一个50万PV的资料类网站(从磁盘提取文档到内存)原服务器32位,1.5G的堆,用户反馈网站比较缓慢,因此公司决定升级,新的服务器为64位,16G的堆内存,结果用户反馈卡顿十分严重,反而比以前效率更低了

    a. 为什么原网站慢?很多用户浏览数据,很多数据load到内存,内存不足,频繁GC,STW长,响应时间变慢

    b. 为什么会更卡顿?内存越大,FGC时间越长

    c. 咋办?PS -> PN + CMS 或者 G1
  2. 系统CPU经常100%,如何调优?(面试高频)CPU100%那么一定有线程在占用系统资源,

    a. 找出哪个进程cpu高(top)

    b. 该进程中的哪个线程cpu高(top -Hp)

    c. 导出该线程的堆栈 (jstack)

    d. 查找哪个方法(栈帧)消耗时间 (jstack)

    e. 工作线程占比高 | 垃圾回收线程占比高
  3. 系统内存飙高,如何查找问题?(面试高频)

    a. 导出堆内存 (jmap)

    b. 分析 (jhat jvisualvm mat jprofiler … )
  4. 如何监控JVM

    a. jstat jvisualvm jprofiler arthas top…



解决JVM运行中的问题



一个案例理解常用工具

  1. 测试代码:
package com.aiz.jvm.gc;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.concurrent.ScheduledThreadPoolExecutor;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;

/**
 * 从数据库中读取信用数据,套用模型,并把结果进行记录和传输
 */

public class T15_FullGC_Problem01 {

    private static class CardInfo {
        BigDecimal price = new BigDecimal(0.0);
        String name = "张三";
        int age = 5;
        Date birthdate = new Date();

        public void m() {}
    }

    private static ScheduledThreadPoolExecutor executor = new ScheduledThreadPoolExecutor(50,
            new ThreadPoolExecutor.DiscardOldestPolicy());

    public static void main(String[] args) throws Exception {
        executor.setMaximumPoolSize(50);

        for (;;){
            modelFit();
            Thread.sleep(100);
        }
    }

    private static void modelFit(){
        List<CardInfo> taskList = getAllCardInfo();
        taskList.forEach(info -> {
            // do something
            executor.scheduleWithFixedDelay(() -> {
                //do sth with info
                info.m();

            }, 2, 3, TimeUnit.SECONDS);
        });
    }

    private static List<CardInfo> getAllCardInfo(){
        List<CardInfo> taskList = new ArrayList<>();

        for (int i = 0; i < 100; i++) {
            CardInfo ci = new CardInfo();
            taskList.add(ci);
        }

        return taskList;
    }
}
  1. java -Xms200M -Xmx200M -XX:+PrintGC com.mashibing.jvm.gc.T15_FullGC_Problem01
  2. 一般是运维团队首先受到报警信息(CPU Memory)
  3. top命令观察到问题:内存不断增长 CPU占用率居高不下
  4. top -Hp 观察进程中的线程,哪个线程CPU和内存占比高
  5. jps定位具体java进程jstack 定位线程状况,重点关注:WAITING BLOCKEDeg.waiting on <0x0000000088ca3310> (a java.lang.Object)假如有一个进程中100个线程,很多线程都在waiting on ,一定要找到是哪个线程持有这把锁怎么找?搜索jstack dump的信息,找 ,看哪个线程持有这把锁RUNNABLE作业:1:写一个死锁程序,用jstack观察 2 :写一个程序,一个线程持有锁不释放,其他线程等待
  6. 为什么阿里规范里规定,线程的名称(尤其是线程池)都要写有意义的名称怎么样自定义线程池里的线程名称?(自定义ThreadFactory)
  7. jinfo pid
  8. jstat -gc 动态观察gc情况 / 阅读GC日志发现频繁GC / arthas观察 / jconsole/jvisualVM/ Jprofiler(最好用)jstat -gc 4655 500 : 每个500个毫秒打印GC的情况如果面试官问你是怎么定位OOM问题的?如果你回答用图形界面(错误)1:已经上线的系统不用图形界面用什么?(cmdline arthas)2:图形界面到底用在什么地方?测试!测试的时候进行监控!(压测观察)
  9. jmap – histo 4655 | head -20,查找有多少对象产生
  10. jmap -dump:format=b,file=xxx pid :线上系统,内存特别大,jmap执行期间会对进程产生很大影响,甚至卡顿(电商不适合)1:设定了参数HeapDump,OOM的时候会自动产生堆转储文件2:很多服务器备份(高可用),停掉这台服务器对其他服务器不影响3:在线定位(一般小点儿公司用不到)
  11. java -Xms20M -Xmx20M -XX:+UseParallelGC -XX:+HeapDumpOnOutOfMemoryError com.mashibing.jvm.gc.T15_FullGC_Problem01
  12. 使用MAT / jhat /jvisualvm 进行dump文件分析https://www.cnblogs.com/baihuitestsoftware/articles/6406271.htmljhat -J-mx512M xxx.dumphttp://192.168.17.11:7000拉到最后:找到对应链接可以使用OQL查找特定问题对象
  13. 找到代码的问题



jconsole远程连接

1、程序启动加入参数:

java -Djava.rmi.server.hostname=192.168.17.11 
-Dcom.sun.management.jmxremote 
-Dcom.sun.management.jmxremote.port=11111 
-Dcom.sun.management.jmxremote.authenticate=false 
-Dcom.sun.management.jmxremote.ssl=false XXX

2、如果遭遇 Local host name unknown:XXX的错误,修改/etc/hosts文件,把XXX加入进去

192.168.17.11 basic localhost localhost.localdomain localhost4 
localhost4.localdomain4
::1         localhost localhost.localdomain localhost6 localhost6.localdomain6

3、关闭linux防火墙(实战中应该打开对应端口)

service iptables stop
chkconfig iptables off #永久关闭

4、windows上打开 jconsole远程连接 192.168.17.11:11111



jvisualvm远程连接

https://www.cnblogs.com/liugh/p/7620336.html (简单做法)



arthas在线排查工具

  • 为什么需要在线排查?在生产上我们经常会碰到一些不好排查的问题,例如线程安全问题,用最简单的threaddump或者heapdump不好查到问题原因。为了排查这些问题,有时我们会临时加一些日志,比如在一些关键的函数里打印出入参,然后重新打包发布,如果打了日志还是没找到问题,继续加日志,重新打包发布。对于上线流程复杂而且审核比较严的公司,从改代码到上线需要层层的流转,会大大影响问题排查的进度。
  • 观察jvm信息
  • thread定位线程问题
  • dashboard 观察系统情况
  • heapdump + jhat分析
  • jad反编译动态代理生成类的问题定位第三方的类(观察代码)版本问题(确定自己最新提交的版本是不是被使用)
  • redefine 热替换目前有些限制条件:只能改方法实现(方法已经运行完成),不能改方法名, 不能改属性m() -> mm()
  • sc – search class
  • watch – watch method
  • 没有包含的功能:jmap



案例汇总

OOM产生的原因多种多样,有些程序未必产生OOM,不断FGC(CPU飙高,但内存回收特别少) (上面案例)

  1. 硬件升级系统反而卡顿的问题(见上)
  2. 线程池不当运用产生OOM问题(见上)不断的往List里加对象(实在太LOW)
  3. smile jira问题实际系统不断重启解决问题 加内存 + 更换垃圾回收器 G1真正问题在哪儿?不知道
  4. tomcat http-header-size过大问题(Hector)
  5. lambda表达式导致方法区溢出问题(MethodArea / Perm Metaspace)LambdaGC.java -XX:MaxMetaspaceSize=9M -XX:+PrintGCDetails
"C:\Program Files\Java\jdk1.8.0_181\bin\java.exe" -XX:MaxMetaspaceSize=9M -XX:+PrintGCDetails "-javaagent:C:\Program Files\JetBrains\IntelliJ IDEA Community Edition 2019.1\lib\idea_rt.jar=49316:C:\Program Files\JetBrains\IntelliJ IDEA Community Edition 2019.1\bin" -Dfile.encoding=UTF-8 -classpath "C:\Program Files\Java\jdk1.8.0_181\jre\lib\charsets.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\deploy.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\ext\access-bridge-64.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\ext\cldrdata.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\ext\dnsns.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\ext\jaccess.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\ext\jfxrt.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\ext\localedata.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\ext\nashorn.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\ext\sunec.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\ext\sunjce_provider.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\ext\sunmscapi.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\ext\sunpkcs11.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\ext\zipfs.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\javaws.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\jce.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\jfr.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\jfxswt.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\jsse.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\management-agent.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\plugin.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\resources.jar;C:\Program Files\Java\jdk1.8.0_181\jre\lib\rt.jar;C:\work\ijprojects\JVM\out\production\JVM;C:\work\ijprojects\ObjectSize\out\artifacts\ObjectSize_jar\ObjectSize.jar" com.mashibing.jvm.gc.LambdaGC
[GC (Metadata GC Threshold) [PSYoungGen: 11341K->1880K(38400K)] 11341K->1888K(125952K), 0.0022190 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
[Full GC (Metadata GC Threshold) [PSYoungGen: 1880K->0K(38400K)] [ParOldGen: 8K->1777K(35328K)] 1888K->1777K(73728K), [Metaspace: 8164K->8164K(1056768K)], 0.0100681 secs] [Times: user=0.02 sys=0.00, real=0.01 secs] 
[GC (Last ditch collection) [PSYoungGen: 0K->0K(38400K)] 1777K->1777K(73728K), 0.0005698 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
[Full GC (Last ditch collection) [PSYoungGen: 0K->0K(38400K)] [ParOldGen: 1777K->1629K(67584K)] 1777K->1629K(105984K), [Metaspace: 8164K->8156K(1056768K)], 0.0124299 secs] [Times: user=0.06 sys=0.00, real=0.01 secs] 
java.lang.reflect.InvocationTargetException
  at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
  at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
  at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
  at java.lang.reflect.Method.invoke(Method.java:498)
  at sun.instrument.InstrumentationImpl.loadClassAndStartAgent(InstrumentationImpl.java:388)
  at sun.instrument.InstrumentationImpl.loadClassAndCallAgentmain(InstrumentationImpl.java:411)
Caused by: java.lang.OutOfMemoryError: Compressed class space
  at sun.misc.Unsafe.defineClass(Native Method)
  at sun.reflect.ClassDefiner.defineClass(ClassDefiner.java:63)
  at sun.reflect.MethodAccessorGenerator$1.run(MethodAccessorGenerator.java:399)
  at sun.reflect.MethodAccessorGenerator$1.run(MethodAccessorGenerator.java:394)
  at java.security.AccessController.doPrivileged(Native Method)
  at sun.reflect.MethodAccessorGenerator.generate(MethodAccessorGenerator.java:393)
  at sun.reflect.MethodAccessorGenerator.generateSerializationConstructor(MethodAccessorGenerator.java:112)
  at sun.reflect.ReflectionFactory.generateConstructor(ReflectionFactory.java:398)
  at sun.reflect.ReflectionFactory.newConstructorForSerialization(ReflectionFactory.java:360)
  at java.io.ObjectStreamClass.getSerializableConstructor(ObjectStreamClass.java:1574)
  at java.io.ObjectStreamClass.access$1500(ObjectStreamClass.java:79)
  at java.io.ObjectStreamClass$3.run(ObjectStreamClass.java:519)
  at java.io.ObjectStreamClass$3.run(ObjectStreamClass.java:494)
  at java.security.AccessController.doPrivileged(Native Method)
  at java.io.ObjectStreamClass.<init>(ObjectStreamClass.java:494)
  at java.io.ObjectStreamClass.lookup(ObjectStreamClass.java:391)
  at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1134)
  at java.io.ObjectOutputStream.defaultWriteFields(ObjectOutputStream.java:1548)
  at java.io.ObjectOutputStream.writeSerialData(ObjectOutputStream.java:1509)
  at java.io.ObjectOutputStream.writeOrdinaryObject(ObjectOutputStream.java:1432)
  at java.io.ObjectOutputStream.writeObject0(ObjectOutputStream.java:1178)
  at java.io.ObjectOutputStream.writeObject(ObjectOutputStream.java:348)
  at javax.management.remote.rmi.RMIConnectorServer.encodeJRMPStub(RMIConnectorServer.java:727)
  at javax.management.remote.rmi.RMIConnectorServer.encodeStub(RMIConnectorServer.java:719)
  at javax.management.remote.rmi.RMIConnectorServer.encodeStubInAddress(RMIConnectorServer.java:690)
  at javax.management.remote.rmi.RMIConnectorServer.start(RMIConnectorServer.java:439)
  at sun.management.jmxremote.ConnectorBootstrap.startLocalConnectorServer(ConnectorBootstrap.java:550)
  at sun.management.Agent.startLocalManagementAgent(Agent.java:137)
  1. 直接内存溢出问题(少见)《深入理解Java虚拟机》P59,使用Unsafe分配直接内存,或者使用NIO的问题
  2. 栈溢出问题-Xss设定太小
  3. 比较一下这两段程序的异同,分析哪一个是更优的写法:
Object o = null;
for(int i=0; i<100; i++) {
    o = new Object();
    //业务处理
}
for(int i=0; i<100; i++) {
    Object o = new Object();
}
  1. 重写finalize引发频繁GC小米云,HBase同步系统,系统通过nginx访问超时报警,最后排查,C++程序员重写finalize引发频繁GC问题为什么C++程序员会重写finalize?(new delete)finalize耗时比较长(200ms)
  2. 如果有一个系统,内存一直消耗不超过10%,但是观察GC日志,发现FGC总是频繁产生,会是什么引起的?System.gc() (这个比较Low)
  3. Distuptor有个可以设置链的长度,如果过大,然后对象大,消费完不主动释放,会溢出 (来自 死物风情)
  4. 用jvm都会溢出,mycat用崩过,1.6.5某个临时版本解析sql子查询算法有问题,9个exists的联合sql就导致生成几百万的对象(来自 死物风情)
  5. new 大量线程,会产生 native thread OOM,(low)应该用线程池,解决方案:减少堆空间(太TMlow了),预留更多内存产生native threadJVM内存占物理内存比例 50% – 80%



问答

  1. -XX:MaxTenuringThreshold控制的是什么?A: 对象升入老年代的年龄 B: 老年代触发FGC时的内存垃圾比例
  2. 生产环境中,倾向于将最大堆内存和最小堆内存设置为:(为什么?)A: 相同 B:不同
  3. JDK1.8默认的垃圾回收器是:A: ParNew + CMS B: G1 C: PS + ParallelOld D: 以上都不是
  4. 什么是响应时间优先?
  5. 什么是吞吐量优先?
  6. ParNew和PS的区别是什么?
  7. ParNew和ParallelOld的区别是什么?(年代不同,算法不同)
  8. 长时间计算的场景应该选择:A:停顿时间 B: 吞吐量
  9. 大规模电商网站应该选择:A:停顿时间 B: 吞吐量
  10. HotSpot的垃圾收集器最常用有哪些?
  11. 常见的HotSpot垃圾收集器组合有哪些?
  12. JDK1.7 1.8 1.9的默认垃圾回收器是什么?如何查看?
  13. 所谓调优,到底是在调什么?
  14. 如果采用PS + ParrallelOld组合,怎么做才能让系统基本不产生FGC
  15. 如果采用ParNew + CMS组合,怎样做才能够让系统基本不产生FGC1.加大JVM内存2.加大Young的比例3.提高Y-O的年龄4.提高S区比例5.避免代码内存泄漏
  16. G1是否分代?G1垃圾回收器会产生FGC吗?
  17. 如果G1产生FGC,你应该做什么?

    a. 扩内存

    b. 提高CPU性能(回收的快,业务逻辑产生对象的速度固定,垃圾回收越快,内存空间越大)

    c. 降低MixedGC触发的阈值,让MixedGC提早发生(默认是45%)
  18. 问:生产环境中能够随随便便的dump吗?小堆影响不大,大堆会有服务暂停或卡顿(加live可以缓解),dump前会有FGC
  19. 问:常见的OOM问题有哪些?栈 堆 MethodArea 直接内存



参考链接


  1. https://blogs.oracle.com/jonthecollector/our-collectors

  2. https://docs.oracle.com/javase/8/docs/technotes/tools/unix/java.html

  3. http://java.sun.com/javase/technologies/hotspot/vmoptions.jsp
  4. JVM调优参考文档:

    https://docs.oracle.com/en/java/javase/13/gctuning/introduction-garbage-collection-tuning.html#GUID-8A443184-7E07-4B71-9777-4F12947C8184

  5. https://www.cnblogs.com/nxlhero/p/11660854.html

    在线排查工具

  6. https://www.jianshu.com/p/507f7e0cc3a3

    arthas常用命令
  7. Arthas手册:

    a. 启动arthas java -jar arthas-boot.jar

    b. 绑定java进程

    c. dashboard命令观察系统整体情况

    d. help 查看帮助

    e. help xx 查看具体命令帮助
  8. jmap命令参考:

    https://www.jianshu.com/p/507f7e0cc3a3


    a. jmap -heap pid

    b. jmap -histo pid

    c. jmap -clstats pid



版权声明:本文为weixin_36091079原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。