关于Java启动时的速度

很多流量大的Java应用在重启的瞬间很容易出现负载比较高的现象,通常会看到的原因可能是GC线程、业务处理线程以及JVM编译线程耗CPU较多,这个问题在目前要解决其实是比较困难的,原因如下。

Java程序在启动的时候所有代码的执行都处于解释执行模式,只有在运行了一段时间后,根据代码方法执行的次数,或代码里循环的执行次数等达到一定的阈值才会编译成机器码,编译成机器码后执行效率会得到大幅提升,而随着执行时间进一步拉长,JVM的各种更高级的编译优化手段就会逐渐加上,例如if条件的执行状况,逃逸分析等,具体的更多信息可以看看以前撒迦写的Java执行的PPT。

因此Java程序要达到一个比较稳定的高效的代码执行是需要一定的时间的,为了解决这种问题,通常来说暂时可以采用的解决方法是:
1. 主动对Java程序进行热身
在启动完成后,主动的访问热点的代码入口,确保主要的热点代码编译成机器码后再放入流量,可通过-XX:+PrintCompilation来确认。

2. 逐步放进流量
通过apache/nginx转发等逐步的放入流量,用流量来完成Java程序的热身也是一种方法,但通常来说这个操作起来比较复杂。

对于特别重要的应用,建议用第一种方法,不过通常操作起来也比较折腾。

在写一些micro benchmark代码前也请一定要记得先做warm动作,避免测试结果偏差太大。

另外,Oracle JDK从JDK 6u25以后的版本支持了多层编译(-XX:+TieredCompilation),默认是不打开的(可以用jinfo -flag或-XX:+PrintFlagsFinal来确认是否打开),这个的好处是之前server都是采用c2高级编译的,会比较耗时且要运行一段时间才会触发编译,而c1编译是比较轻量的也比较快触发,因此在启用了多层编译后,可以在启动后更快的让部分代码先进入编译模式,感兴趣的同学可以自行找下关于多层编译的一些资料。

之前听到一个消息是,Oracle JDK为了解决某个问题做的一个改进,有可能能用于提升Java应用的启动速度,也算是无心摘柳柳成荫,:),不过暂时貌似还没有什么新的进展的消息。

另外,再啰嗦说下,传说中的大方法的执行效率更低,是有可能的…原因是inline优化,Oracle JDK会有默认的MaxInlineSize的控制,如果大于了这个值,在做Inline优化的时候就会跳过,从而导致在执行方法时要多几个指令,因此方法的大小还是要稍微控制下的。

关于Java程序执行的一些原理知识,推荐看下@rednaxelafx之前写的一个巨长的PPT,:)

昨天的调查结果让我还比较欣慰,结果显示订阅我这个账号的大部分是非阿里的,挺好,:),不过话说这是我这个公众账号一天收到的最多消息的一次,希望大家有什么问题,或希望看到分享的,或希望给其他人分享的都回复我,如果有希望给其他人分享的最好了,现在微信5.0已经支持在公众账号上写作者名字了。

最后推荐下阿里技术嘉年华的微信公众号:alibabatech 会有很多阿里各种技术的分享信息,阿里在技术上还是一家比较开放的公司,因此还是能得到一些信息的。

话说阿里技术嘉年华应该算是搞得很不错,干货很多的技术大会,尽管今年开始收费了(MM不收费,这个一定要继续保持下去,:)),但价格很便宜,所以能来参加的话我觉得还是值得参加下的(尽管我个人现在对各类技术大会都不感兴趣了…)。

=============================
题图来源于:http://img0.pcauto.com.cn/pcauto/1108/31/1624710_21.jpg
欢迎关注微信公众号:hellojavacases

关于此微信号:
分享Java问题排查的Case、Java业界的动态和新技术、Java的一些小知识点Test,以及和大家一起讨论一些Java问题或场景,这里只有Java细节的分享,没有大道理、大架构和大框架。

公众号上发布的消息都存放在http://hellojava.info上。

发表评论

电子邮件地址不会被公开。 必填项已用*标注


*