Java与C++之间有一堵由内存动态分配和垃圾收集技术所围成的“高墙”,墙外面的人想进去,墙里面的人却想出来。
天弘基金的爱理财app已经积累了220w用户,当一个应用的体量变得越来越大,优化就变成了必不可少的一部分。这篇文章与读者分享一下爱理财后台管理系统(boss系统)的调优案例。
a. 装载(load)
i. 开始时机:
1) new实例化对象时,若类没有加载
2) 读取或设置一个类static字段,若类没有被加载。final除外,因为final字段的值已经在编译期放到了常量池中
3) 调用类的static方法
4) 反射调用类
5) 初始化一个类时,若父类没有被加载,会先加载父类
ii. 不会加载类的情况
1) 通过子类去引用父类的static字段,不会导致子类加载
2) 数组定义引用类,不会导致类加载。 如 Student[] stu = new Student[10], student类不会被加载
3) 读取类的final字段,不会导致类加载。
iii. 流程
1) 通过类的全限定名获取定义此类的二进制流。可以从class文件,网络,或者运行时计算(如动态代理)出这个二进制流
2) 将字节流代表的static存储结构转化为方法区的运行时数据结构,也就是存储到方法区中
3) 内存中生成一个代表此类的class对象
b. 链接
i. 验证
1) 目的:防止加载的class文件危害虚拟机本身安全
2) 流程:
a) 文件格式验证,如magic是否为0xCAFEBABE,主次版本号是否在当前VM能处理范围内
b) 元数据验证,主要验证描述信息是否符合Java语言规范
c) 字节码验证,最复杂,通过数据流和控制流分析,确定程序语义是合法的,符合逻辑的
d) 符号引用验证,如通过全限定名能否找到类,字段方法的可访问性等。
ii. 准备
1) 目的:为static变量分配内存,并将它们统一初始化为0. static final除外
iii. 解析
1) 目的:将常量池中的符号引用替换为直接引用
a) 符号引用:字面量,如类名,方法名等
b) 直接引用:类或方法存放在内存中的地址
c. 初始化
i. 初始化static变量为实际的值。通过执行类构造器方法来完成。这个方法是编译器自动生成在字节码中的
ii. clinit:
1) static变量的赋值 + static{}语句块。 static{}语句块只能访问到定义在它之前的变量。
2) clinit和实例构造器init不同,不需要显式调用父类构造器。JVM保证子类的clinit执行前,父类的clinit肯定被执行过
3) 父类的clinit先执行,故父类中的static{}语句块在子类的static变量赋值前被调用
4) 接口中不能使用static{}语句块,但仍然可以为变量赋值
5) JVM可以保证clinit方法是线程安全的。多个线程同时去初始化一个类,只有一个线程会执行clinit方法,其他都会阻塞等待。
累的装载阶段和初始化阶段我们无法干预,在链接阶段的三步中准备步骤和解析步骤也是必不可少。考虑到实际情况:boss系统的war包是通过公司内jekins编译生成,jetty使用者甚多,它的编译代码我们可以认为是可靠的,不需要在加载的时候再进行字节码验证,因此通过参数-Xverify:none禁止掉字节码验证过程也可作为一项优化措施。加入这个参数后,boss系统在启动时的启动数据如图4:
0.802: [GC [PSYoungGen: 15360K->2534K(17920K)] 15360K->4419K(58368K), 0.0091330 secs] [Times: user=0.01 sys=0.00, real=0.00 secs]
1.178: [GC [PSYoungGen: 17894K->2551K(33280K)] 19779K->4988K(73728K), 0.0080680 secs] [Times: user=0.01 sys=0.00, real=0.01 secs]
1.312: [GC [PSYoungGen: 33244K->2168K(33280K)] 35681K->4676K(73728K), 0.0064580 secs] [Times: user=0.01 sys=0.00, real=0.01 secs]
1.534: [GC [PSYoungGen: 32888K->2168K(64000K)] 35396K->4676K(104448K), 0.0068860 secs] [Times: user=0.01 sys=0.00, real=0.00 secs]
1.847: [GC [PSYoungGen: 63608K->2328K(64000K)] 66116K->4836K(104448K), 0.0075480 secs] [Times: user=0.01 sys=0.00, real=0.01 secs]
4.603: [GC [PSYoungGen: 63768K->2840K(126976K)] 66276K->5356K(167424K), 0.0112090 secs] [Times: user=0.01 sys=0.00, real=0.01 secs]
6.632: [GC [PSYoungGen: 125720K->4576K(127488K)] 128236K->31786K(167936K), 0.0394160 secs] [Times: user=0.05 sys=0.01, real=0.03 secs]
6.672: [Full GC [PSYoungGen: 4576K->0K(127488K)] [ParOldGen: 27209K->28310K(64512K)] 31786K->28310K(192000K) [PSPermGen: 9490K->9453K(21504K)], 0.0952790 secs] [Times: user=0.16 sys=0.00, real=0.10 secs]
8.022: [GC [PSYoungGen: 122880K->17404K(216576K)] 151190K->56530K(281088K), 0.0423470 secs] [Times: user=0.05 sys=0.01, real=0.05 secs]
9.572: [GC [PSYoungGen: 216572K->25572K(254976K)] 255698K->99064K(328704K), 0.0654460 secs] [Times: user=0.08 sys=0.01, real=0.07 secs]
9.637: [Full GC [PSYoungGen: 25572K->0K(254976K)] [ParOldGen: 73492K->73142K(133632K)] 99064K->73142K(388608K) [PSPermGen: 9461K->9459K(21504K)], 0.1431700 secs] [Times: user=0.24 sys=0.00, real=0.14 secs]
11.089: [GC [PSYoungGen: 229376K->44539K(259072K)] 302518K->127289K(392704K), 0.0825660 secs] [Times: user=0.08 sys=0.02, real=0.08 secs]
13.533: [GC [PSYoungGen: 259067K->38203K(252928K)] 341817K->151321K(386560K), 0.0859670 secs] [Times: user=0.16 sys=0.01, real=0.09 secs]
13.619: [Full GC [PSYoungGen: 38203K->0K(252928K)] [ParOldGen: 113117K->95891K(173056K)] 151321K->95891K(425984K) [PSPermGen: 14776K->14772K(25088K)], 0.2183000 secs] [Times: user=0.42 sys=0.01, real=0.22 secs]
17.131: [GC [PSYoungGen: 214528K->14529K(270336K)] 310419K->110420K(443392K), 0.0266560 secs] [Times: user=0.04 sys=0.00, real=0.03 secs]
18.915: [GC [PSYoungGen: 224961K->7865K(218624K)] 320852K->103764K(391680K), 0.0290080 secs] [Times: user=0.05 sys=0.00, real=0.02 secs]
21.433: [GC [PSYoungGen: 218297K->13869K(268800K)] 314196K->109769K(441856K), 0.0722460 secs] [Times: user=0.13 sys=0.00, real=0.08 secs]
685.158: [GC [PSYoungGen: 227373K->34562K(265728K)] 323273K->130461K(438784K), 0.0559120 secs] [Times: user=0.09 sys=0.00, real=0.05 secs]
702.625: [GC [PSYoungGen: 248066K->21341K(271872K)] 343965K->117240K(444928K), 0.0353460 secs] [Times: user=0.07 sys=0.00, real=0.04 secs]
724.756: [GC [PSYoungGen: 240989K->21517K(271872K)] 336888K->117416K(444928K), 0.0390940 secs] [Times: user=0.07 sys=0.00, real=0.04 secs]
-Xverify:none -Xms2048m -Xmx2048m -Xss512k -XX:NewSize=1024M -XX:MaxNewSize=1024M -XX:PermSize=256m -XX:MaxPermSize=256m -Xnoclassgc -XX:+PrintGCDetails -Xloggc:/home/admin/logs/trade_gc.log
-server -Xverify:none -Xms2048m -Xmx2048m -Xss512k -XX:NewSize=1024M -XX:MaxNewSize=1024M -XX:PermSize=256m -XX:MaxPermSize=256m -Xnoclassgc -XX:+UseParNewGC -XX:+UseConcMarkSweepGC -XX:+PrintGCDetails -Xloggc:/home/admin/logs/trade_gc.log