说说在Java启动参数上易犯的错

简介:

作者:林昊

mistake

前几年在将OS从32 bit升级到64 bit,以及虚拟机的内存调整到8G后,我把应用的Java启动参数重新写了一版,作为目前大部分Java应用的默认启动参数模版,这几年下来,发现在这个标准版的启动参数上还是犯了一些错误的。

 

1. -XX:+DisableExplicitGC
Java在实现RMI Server的时候会通过定时的调System.gc来强制做GC(即使程序里没用到RMI也会被启动),这个动作非常烦人,另外也是为了避免应用代码上显式去调用System.gc导致一些没必要的GC动作产生,所以当时就直接加上了这个参数。

现在来看,这个参数有个挺大的问题是,Direct ByteBuffer所占用的内存以及FileChannel.map所占用的内存当达到了他们的最大阈值时,需要依赖调用System.gc来强制释放下,如果加上了这个启动参数,就意味着这个强制的释放就无效了,这会导致的一个问题是,当old gen还没到达触发full gc/cms gc的条件,而堆外的Direct ByteBuffer/FileChannel.map占用的空间又超过了它们的最大阈值时,就会直接导致OOM,而这种情况下很有可能其实是可以借助显式调用System.gc来释放出足够的空间,不过话说我仍然觉得这是JDK设计上应该改进的一点,不应该在这个时候需要依赖System.gc来管理堆外的空间,大家可以翻下FileChannel.map的代码就会发现那里在等待System.gc执行的结果是写S的等待100ms,事实上很少有full gc/cms gc可以在100ms完成。

 

不过鉴于上面的状况,如果应用里有使用到不少Direct ByteBuffer或FileChannel.map的话,建议还是不要开启-XX:+DisableExplicitGC,如果是cms gc的,还是改为加上这个参数-XX:+ExplicitGCInvokesConcurrent,另外如果有RMI Server这种定时GC影响的,再调整下-Dsun.rmi.dgc.client.gcInterval和-Dsun.rmi.dgc.server.gcInterval这两个时间吧,时间单位是ms,也可以设置为Long.MAX_VALUE。

 

2. 缺少-XX:+UseCMSInitiatingOccupancyOnly
由于我们的Java应用的heap基本都是大于4G的,所以都是用的CMS,当时我在写启动参数的时候一直犹豫要不要加上-XX:+UseCMSInitiatingOccupancyOnly这个参数,一犹豫就没加,但事实上后来碰到了不少应用由于JVM自行触发CMS GC的机制导致CMS GC频繁,所以建议用CMS GC的场景下还是加上这个参数更稳妥。

 

3. -XX:MaxDirectMemorySize
话说在写启动参数的时候我都压根不知道这参数(要知道Java到底有哪些启动参数可用,以及默认值是多少,最靠谱的方法是在启动参数上加-XX:+PrintFlagsFinal或用jinfo -flags [pid]来查看),后来是由于有一次出现了有应用物理内存被耗光,排查的时候才发现是Direct ByteBuffer这块默认的大小是heap size,所以在有些情况下可能会出现Direct ByteBuffer这里占用了大量的空间,但heap这边又还不到触发Full gc/CMS gc的条件,就会有可能导致物理内存被耗光。
因此对于远程交互比较多的应用,建议还是加上这个参数,合理控制大小,不要让heap size+Direct Memory Size就把物理内存给耗光了。

 

ps: 关于Java常见问题的排查方法,重新专门写了一个PPT,涵盖了以下几种常见的Java问题的排查方法:
1. 类加载问题,例如NoSuchMethodException;
2. 内存问题,例如各种OOM;
3. 应用无响应问题,例如http访问后返回499;
4. CPU利用率问题,例如us耗尽;
5. Java进程退出问题。

相关文章
|
1月前
|
存储 Java
Java-参数传值
Java-参数传值
25 4
|
1月前
|
Java
【Java每日一题】— —第二十二题:类名作参数进行方法调用的传递问题。
【Java每日一题】— —第二十二题:类名作参数进行方法调用的传递问题。
23 1
|
4月前
|
前端开发 Java 数据库连接
9:参数校验-Java Spring
9:参数校验-Java Spring
30 0
|
1月前
|
存储 Java fastjson
Java泛型-4(类型擦除后如何获取泛型参数)
Java泛型-4(类型擦除后如何获取泛型参数)
33 1
|
21天前
|
缓存 Java C#
【JVM故障问题排查心得】「Java技术体系方向」Java虚拟机内存优化之虚拟机参数调优原理介绍(一)
【JVM故障问题排查心得】「Java技术体系方向」Java虚拟机内存优化之虚拟机参数调优原理介绍
60 0
|
7天前
|
存储 监控 安全
泛型魔法:解码Java中的类型参数
泛型魔法:解码Java中的类型参数
26 0
泛型魔法:解码Java中的类型参数
|
1月前
|
前端开发 Java Spring
Java 新手如何使用Spring MVC 中的查询字符串和查询参数
Java 新手如何使用Spring MVC 中的查询字符串和查询参数
|
2月前
|
NoSQL Java Redis
【Java专题_09】生产环境Jvm参数设置
【Java专题_09】生产环境Jvm参数设置
|
2月前
|
Java
深入了解 Java 方法和参数的使用方法
方法是一块仅在调用时运行的代码。您可以将数据(称为参数)传递到方法中。方法用于执行特定的操作,它们也被称为函数。
104 4
|
4月前
|
Java
Java【代码分享 11】yaml配置List和Map参数对象的配置信息及类文件实例分享(效仿GatewayDynamic+DynamicDataSource的注入方法)
Java【代码分享 11】yaml配置List和Map参数对象的配置信息及类文件实例分享(效仿GatewayDynamic+DynamicDataSource的注入方法)
47 0