直播: 近二十载从业老兵谈金融科技赋能的探索与实践
JVM 参数是什么
大家照相通常使用手机就够用了, 但是针对发烧友来说会使用更专业的设备, 比如单反相机, 在单反里有好几个模式, P/A/S/M, 其中 P 是傻瓜模式, 程序会自动根据环境设置快门速度和光圈大小, 以得到相对合适的曝光效果. A 档是光圈优先, 用户可以自己设置光圈大小, 快门速度等都交给相机程序来决定, 类似半自动化的模式. S 档是快门优先模式, 和 A 档类似, 只是用户可以设置快门速度. 最后一个模式是 M 档, 这是纯手动模式, 由用户自己来调整快门速度, 光圈大小等, 这个对人的要求就会很高, 但是很多专家往往都会选择 M 档来拍摄自己的作品.
可以把 JVM 想象成相机, JVM 参数想象成光圈大小, 快门速度之类的参数值, 这些参数对程序的运行会影响挺大.
java 程序跑在 JVM 上, JVM 会根据环境自动设置一些 JVM 参数, 但是这些参数并不能保证一定是最优的, 有些参数在启动的时候就基本设置好了, 它们在运行的时候还无法调整. 为了让 JVM 能更好地运行你的程序, 还是有必要对 JVM 参数有一定的理解, 知道这些 JVM 参数分别在什么场景下有效果, 起到什么作用, 比如我们到底期不期望类可以卸载, 是否可以在运行的时候打印一些日志协助我们了解 JVM 的运行情况, 出问题的时候是否可以自动给我们做一些现场数据的保留等, 这些都是可以通过 JVM 参数来设置的.
JVM 参数有多少
相机调整的无非就那么几个参数值, 那 JVM 参数到底有多少个呢, 大概有 1000 多个, 是不是让你很震惊, 没错, 确实有这么多.
大家可以到 PerfMa 社区 去看看所有这些 JVM 参数(注: 这是 PerfMa 社区专门为大家分享 JVM 参数经验的讨论区), 当然我们不一定非得对每个 JVM 参数要了解清楚, 但是对一些常见的, 有助于性能调优的 JVM 参数还是有必要了解一下的.
JVM 参数通常设置的位置
我们启动一个 java 程序很简单, 命令类似如下
java Main
我们都知道上面的 Main 是程序的启动类, JVM 执行的时候会找到这个 Main 类里的如下签名的函数
Public static void main(String args[])
那这里函数的参数 args 怎么传进来的呢? 我们通过在启动命令的主类后面加上相关的参数, 参数之间用空格分开, JVM 会自动将这些参数作为 args 的组成部分传进来, 比如
java Main arg1 arg2
这样, args 这个数组里自动会填充 arg1 和 arg2 两个元素, 这样在你的程序里就可以使用这些参数了
我们把 arg1 和 arg2 这些叫做程序参数, 但是和我们课程相关的并不是程序参数, 而是 JVM 参数, 那 JVM 参数放到哪里呢? JVM 参数都是放在主类之前, java 命令之后, 比如
java -Xmx100M Main arg1 arg2
这里的 - Xmx100M 其实就是 JVM 参数, 所以所有的 JVM 参数都是放在这个位置的, 如果不是这个位置, 那你设置的 JVM 参数将会是无效的, 如果参数出现不符合预期的情况, 那请第一时间检查的是你 JVM 参数设置的位置, 当然还可能存在一些别的原因导致 JVM 参数和你设置的情况可能不一致的情况
JVM 参数的写法
那 JVM 参数具体怎么写呢, 可以有好几种
"-X" 开头的, 比如 - Xmx100M
"-XX:" 开头的, 比如 - XX:+UseG1GC
"-" 开头的, 比如 - verbose:gc
其中 - X 和 - 开头的通常会被转换为一个或者多个 - XX: 开头的参数, 只是一个简化的写法, 比如说 - Xmx100M,JVM 里会自动转化为 - XX:MaxHeapSize=100M,-verbose:class 会自动转换为 - XX:+TraceClassLoading -XX:+TraceClassUnloading
通过 Flags 参数指定 JVM 参数文件
如果 JVM 参数都和源码伴着一起发布的话, 如果仅仅修改 JVM 参数也必须拉个分支提交代码, 这不是很友好, 有什么好办法呢?
我们可以在启动参数里设置一个参数就好, 这个参数类似如下
java -XX:Flags=/home/admin/flags Main arg1 arg2
设置过这个参数之后, 我们只要在服务的 / home/admin 目录下创建 flags 文件, 同时在这个文件里指定所有的 JVM 参数就可以了, 但是对 flags 文件里的参数写法会有些要求,-X 之类的参数不能设置, 但是可以用其等价的 - XX 的参数来替代, 比如说 - Xmx100M, 只能用 - XX:MaxHeapSize=100M 来取代, 同时在文件里不要出现 - XX:, 只要 key=value 或许 +/-key 就可以了, 不同的参数之间用换行或者空格分开即可, 比如 flags 文件的内容如下:
MaxHeapSize=8G +UseG1GC
其实等价于
-Xmx8G -XX:+UseG1GC
可以通过加上 - XX:+PrintVMOptions 可以打印设置过的 JVM 参数来验证, 比如
java -XX:Flags=/home/admin/flags -XX:+PrintVMOptions Main arg1 arg2
通过 VMOptionsFile 参数来指定 JVM 参数文件
使用上面的 Flags 参数可能会比较别扭, 因为设置参数和我们正常的写法不太一样, 如果我们的 JDK 版本大于 1.8 的话, JVM 提供了一个更人性化的参数, 那就是 VMOptionsFile 来取代 Flags, 这也是指定一个文件, 这个文件里的 JVM 参的写法和我们在 java 命令后写的 JVM 参数写法完全一样
java -XX:VMOptionsFile=/home/admin/flags Main arg1 arg2
在 flags 文件里我们可以这么写
-Xmx8G -XX:+UseG1GC
是不是方便了很多呢?
来源: http://zhuanlan.51cto.com/art/202004/615014.htm