说说在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进程退出问题。

相关文章
|
2月前
|
Java
实现java执行kettle并传参数
实现java执行kettle并传参数
38 1
|
7月前
|
Java
解析Java线程池:参数详解与执行流程
解析Java线程池:参数详解与执行流程
80 1
|
6月前
|
Java API 编译器
Java编译器注解运行和自动生成代码问题之编译时通过参数设置选项值问题如何解决
Java编译器注解运行和自动生成代码问题之编译时通过参数设置选项值问题如何解决
|
6月前
|
缓存 安全 算法
Java面试题:如何通过JVM参数调整GC行为以优化应用性能?如何使用synchronized和volatile关键字解决并发问题?如何使用ConcurrentHashMap实现线程安全的缓存?
Java面试题:如何通过JVM参数调整GC行为以优化应用性能?如何使用synchronized和volatile关键字解决并发问题?如何使用ConcurrentHashMap实现线程安全的缓存?
71 0
|
2月前
|
Java
在Java中定义一个不做事且没有参数的构造方法的作用
Java程序在执行子类的构造方法之前,如果没有用super()来调用父类特定的构造方法,则会调用父类中“没有参数的构造方法”。因此,如果父类中只定义了有参数的构造方法,而在子类的构造方法中又没有用super()来调用父类中特定的构造方法,则编译时将发生错误,因为Java程序在父类中找不到没有参数的构造方法可供执行。解决办法是在父类里加上一个不做事且没有参数的构造方法。
|
3月前
|
存储 算法 Java
java制作海报六:Graphics2D的RenderingHints方法参数详解,包括解决文字不清晰,抗锯齿问题
这篇文章是关于如何在Java中使用Graphics2D的RenderingHints方法来提高海报制作的图像质量和文字清晰度,包括抗锯齿和解决文字不清晰问题的技术详解。
116 0
java制作海报六:Graphics2D的RenderingHints方法参数详解,包括解决文字不清晰,抗锯齿问题
|
3月前
|
Java
java构造方法时对象初始化,实例化,参数赋值
java构造方法时对象初始化,实例化,参数赋值
109 1
|
5月前
|
Java
【Azure 应用服务】如何查看App Service Java堆栈JVM相关的参数默认配置值?
【Azure 应用服务】如何查看App Service Java堆栈JVM相关的参数默认配置值?
【Azure 应用服务】如何查看App Service Java堆栈JVM相关的参数默认配置值?
|
5月前
|
消息中间件 Java 大数据
"深入理解Kafka单线程Consumer:核心参数配置、Java实现与实战指南"
【8月更文挑战第10天】在大数据领域,Apache Kafka以高吞吐和可扩展性成为主流数据流处理平台。Kafka的单线程Consumer因其实现简单且易于管理而在多种场景中受到欢迎。本文解析单线程Consumer的工作机制,强调其在错误处理和状态管理方面的优势,并通过详细参数说明及示例代码展示如何有效地使用KafkaConsumer类。了解这些内容将帮助开发者优化实时数据处理系统的性能与可靠性。
127 7
|
5月前
|
C# 开发者 Windows
震撼发布:全面解析WPF中的打印功能——从基础设置到高级定制,带你一步步实现直接打印文档的完整流程,让你的WPF应用程序瞬间升级,掌握这一技能,轻松应对各种打印需求,彻底告别打印难题!
【8月更文挑战第31天】打印功能在许多WPF应用中不可或缺,尤其在需要生成纸质文档时。WPF提供了强大的打印支持,通过`PrintDialog`等类简化了打印集成。本文将详细介绍如何在WPF应用中实现直接打印文档的功能,并通过具体示例代码展示其实现过程。
479 0