java 代码缓存优化
我犟不过你 人气:0JIT编译器版本
JIT编译器有不同的版本,而最终你使用哪种,取决于你所使用的系统平台。前面的文章我们说到编译器有-client
和-server
,
具体划分应该是如下所示:
-client
32位client编译器-server
32位server编译器-d64
64位server编译器
如果你的系统是32位,那么你只能使用32位JVM,如果你是64位系统,那么可以选择32位或64位系统。
不同jvm的编译器版本如下:
jvm版本 | -client | -server | -d64 |
---|---|---|---|
linux 32位 | 32位client | 32位server | 出错 |
linux 64位 | 64位server | 64位server | 64位server |
windows 32位 | 32位client | 32位server | 出错 |
windows 64位 | 64位server | 64位server | 64位server |
macOS | 64位server | 64位server | 64位server |
我们使用的java8,默认使用的都是server编译器,同时是开启分层编译的。
默认情况JVM如何选择编译器?
假如我们没有指定编译器的参数,那么JVM是如何选择使用何种编译器的呢?
实际上jvm是考虑机器的CPU数目:
- 在64位系统,无论机器多少CPU,都会使用server编译器
- 在32系统
- 如果只有一个cpu,那么使用client编译器
- 多个cpu,使用server编译器。
如何判断当前环境jvm使用的编译器?
我们最经常使用的查看java版本命令,就可以在最后一行展示当前所使用的编译器类型:
[root@public-server9 esmp]# java -version java version "1.8.0_172" Java(TM) SE Runtime Environment (build 1.8.0_172-b11) Java HotSpot(TM) 64-Bit Server VM (build 25.172-b11, mixed mode)
如上所示,Linux环境下使用的是64位server编译器。
小节:
不同的平台环境对应着不同的java版本,不同的java版本又对应着不同的编译器版本。我们在使用的时候,只需要选择对应于平台的java版本,不需要手动指定编译器,仰仗于平台所支持的编译器即可。
常规的调优可能就是选择不同的编译器版本,开放分层编译等。本章,将会具体分析除此以外的编译器优化场景。
代码缓存
JVM在编译代码后,会在代码缓存当中保存编译后的汇编语言指令集。而代码缓存的大小是固定的,换句话说,jvm能够编译的代码数量就是固定的。
前面我们提到过,如果没有被编译成汇编语言的代码,会通过解释执行的方式去运行,性能会大幅下降。所以如何控制代码缓存的大小,是一个我们可以优化的点。
代码缓存占满发生在什么情况?
通常在使用client编译器时,会占用大量的代码缓存,因为其在运行过程中需要编译的代码非常多。相反,server编译器采用优先编译的方式,运行时只会对热点代码进行编译,所以发生代码缓存占满的情况较少。综上所述,在使用分层编译的时候,也有一定的可能存在代码缓存被占满的情况。
代码缓存默认大小
代码缓存在不同版本的java当中,默认代码缓存大小也不相同,如下仅展示java7和java8的部分:
java版本 | 编译器类型 | 代码缓存大小(MB) |
---|---|---|
java7 | 32位 client | 32 |
java7 | 32位 server | 32 |
java7 | 32位 server 分层编译 | 48 |
java8 | 32位 client | 32 |
java8 | 32位 server 分层编译 | 240 |
java8 | 64位 server 分层编译 | 240 |
如上可以发现,java7的代码缓存较小,比较容易出现问题。这也是为什么java7没有默认开启分层编译,而java8则默认开启。
我们可以通过下面的命令查看当前代码缓存的大小,我这里是java8:
[root@hecs-402944 opt]# jps 14186 Jps 1434 jar 655 WrapperSimpleApp [root@hecs-402944 opt]# jinfo -flag ReservedCodeCacheSize 1434 -XX:ReservedCodeCacheSize=251658240
251658240是字节,换算后刚好240M。
如何确定正好的代码缓存?
其实这个需要根据使用情况进行实际调整,通过ReservedCodeCacheSize
可以指定大小。
但是代码缓存的大小的设置要考虑到服务器实际内存的大小。如果我们将其分配过大,则这部分空间会被jvm预留出来,请确定你的服务器是否有足够大的内存。
另一个方面,32位的jvm被允许使用的最大内存为4g,其中还包括堆内存,元空间,栈,以及本地方法等等,所以代码缓存总是会被限制大小的。
在64位机器也不是越大越好,每个机器上的进程有自己的最大内存空间,超过它也是没有效果的。
综上所述,有些大型应用就需要我们对代码缓存进行调优。
如何监控代码缓存?
前面我们学习过jconsole的使用,如果你的服务允许开启jmx服务的话,那么就可以进行监控了,文章地址如下:java性能分析jconsole详解
如下图所示,就是监控代码缓存的动态图标:
我们可以根据监控的结果去调整自己服务的代码缓存大小,我这个服务举例默认的240M还有很大的差距,其实是不需要进行调优的。
加载全部内容