神秘的 JVM 码

有的同学虽然写了一段时间 Java 了,但是对于 JVM 却不太关注。有的同学说,参数都是团队规定好的,部署的时候也不用我动手,关注它有什么用,而且,JVM 这东西,听上去就感觉很神秘很高深的样子,还是算了吧。

没错,部署的时候可能用不到你亲自动手,但是出现问题了怎么办,难道不用你解决问题吗,如果对 JVM 了解不够的话,有些问题可能排查起来就很费力,或者根本无法解决。

本篇以 JDK Hotspot 8 为背景,介绍一下 JVM 的常用参数。建议你在做一些小项目、小 demo 的时候,也把这些参数加上,加深印象。以我的经验来看,有些知识你刚开始接触的时候会感觉很难理解,但是没关系,万事开头难嘛,知识点都是需要消化时间的。第一天不理解,甚至过了一个月也不理解,但是总有那么一刻,你会突然有种茅塞顿开的感觉,感觉一下子通了。最后心里面感谢自己在多少多少天以前能够开始学习并坚持学习这些知识点。

只介绍一些常用参数,除了这些常用参数外,Hotspot 还提供了很多其他的参数,每一个都值得考究。

还是要把内存模型图放在这里,方便理解。

image

堆参数:

-Xms: 堆的初始值,例如 -Xms2048M,初始堆大小为 2G

-Xmx: 堆的最大值,例如 -Xmx2048M,允许最大堆内存 2G

-Xmn: 新生代大小

-XX:SurvivorRatio:Eden 区所占比例,默认是 8,也就是 80%,例如 -XX:SurvivorRatio=8

image

最好将 -Xms 和 -Xmx 的值设置成一样的值,这样做是为了防止随着堆空间使用量增加,会动态的调整堆空间大小,有一定的性能损耗,不如开始就设置成相同的值,来规避性能损失。

栈参数

-Xss:栈空间大小,栈是线程独占的,所以是一个线程使用栈空间的大小,例如 -Xss256K,如果不设置此参数,默认值是 1M,一般来讲设置成 256K 就足够了。

Metaspace 参数

-XX:MetaspaceSize:Metaspace 空间初始大小,如果不设置的话,默认是20.79M,这个初始大小是触发首次 Metaspace Full GC 的阈值,例如 -XX:MetaspaceSize=256M

-XX:MaxMetaspaceSize:Metaspace 最大值,默认不限制大小,但是线上环境建议设置,例如

-XX:MaxMetaspaceSize=256M

-XX:MinMetaspaceFreeRatio:最小空闲比,当 Metaspace 发生 GC 后,会计算 Metaspace 的空闲比,如果空闲比(空闲空间/当前 Metaspace 大小)小于此值,就会触发 Metaspace 扩容。默认值是 40 ,也就是 40%,例如 -XX:MinMetaspaceFreeRatio=40

-XX:MaxMetaspaceFreeRatio:最大空闲比,当 Metaspace 发生 GC 后,会计算 Metaspace 的空闲比,如果空闲比(空闲空间/当前 Metaspace 大小)大于此值,就会触发 Metaspace 释放空间。默认值是 70 ,也就是 70%,例如 -XX:MaxMetaspaceFreeRatio=70

建议将 MetaspaceSize 和 MaxMetaspaceSize 设置为同样大小,避免频繁扩容。

GC 日志

简单日志

-verbose:gc 或者 -XX:+PrintGC

日志格式:

[GC (Allocation Failure) 7892K->5646K(19456K), 0.0060442 secs]

[GC (Allocation Failure) , 0.0066315 secs]

[Full GC (Allocation Failure) 19302K->13646K(19456K), 0.0032698 secs]

详细日志

#打印详细日志

-XX:+PrintGCDetails

#打印 GC 的时间点

-XX:+PrintGCDateStamps

日志格式

2019-11-13T14:06:46.099-0800: [GC (Allocation Failure) 2019-11-13T14:06:46.099-0800: [DefNew (promotion failed) : 9180K->9157K(9216K), 0.0084297 secs]2019-11-13T14:06:46.107-0800: [Tenured: 10145K->10145K(10240K), 0.0035768 secs] 13802K->13646K(19456K), [Metaspace: 3895K->3895K(1056768K)], 0.0120887 secs] [Times: user=0.00 sys=0.00, real=0.02 secs]

2019-11-13T14:06:47.243-0800: [Full GC (Allocation Failure) 2019-11-13T14:06:47.244-0800: [Tenured: 10145K->10145K(10240K), 0.0042686 secs] 19304K->19146K(19456K), [Metaspace: 3895K->3895K(1056768K)], 0.0043232 secs] [Times: user=0.00 sys=0.00, real=0.00 secs]

以下几个 GC 日志相关的参数打印的内容比较多,生产环境可选择性开启,大多数时候不需要开启。

GC 前后的堆信息

-XX:+PrintHeapAtGC

{Heap before GC invocations=0 (full 0):

def new generation total 9216K, used 7892K [0x00000007bec00000, 0x00000007bf600000, 0x00000007bf600000)

eden space 8192K, 96% used [0x00000007bec00000, 0x00000007bf3b5200,

xxx....

class space used 445K, capacity 462K, committed 512K, reserved 1048576K

Heap after GC invocations=1 (full 0):

def new generation total 9216K, used 1023K [0x00000007bec00000,

xxx...

Metaspace used 3892K, capacity 4646K, committed 4864K, reserved 1056768K

class space used 445K, capacity 462K, committed 512K, reserved 1048576K

}

GC 导致的 Stop the world 时间

-XX:+PrintGCApplicationStoppedTime

Total time for which application threads were stopped: 0.0070384 seconds, Stopping threads took: 0.0000200 seconds

加载类信息

-verbose:class

[Loaded java.net.URLClassLoader$3$1 from /Library/Java/JavaVirtualMachines/jdk1.8.0_111.jdk/Contents/Home/jre/lib/rt.jar]

GC 前后的类加载情况

-XX:+PrintClassHistogramBeforeFullGC

-XX:+PrintClassHistogramAfterFullGC

num #instances #bytes class name

----------------------------------------------

1: 140 19016264 [B

2: 2853 226256 [C

3: 138 169072 [I

4: 761 86240 java.lang.Class

5: 2850 68400 java.lang.String

6: 660 41024 [Ljava.lang.Object;

日志输出到文件

以上参数配置好之后,默认会输出到控制台或者服务指定的统一日志的位置。但是这里还会有服务的一般性信息日志、错误日志等,都混在一起的话会比较乱,所以,一般都会把 jvm 日志单独存放。

#GC 活动日志,根据配置的参数输出内容

-Xloggc:/Users/fengzheng/jvmlog/gc.log

`#致命错误日志,只有在 jvm 发生崩溃的时候会输出

-XX:ErrorFile=/Users/fengzheng/jvmlog/hs_err_pid%p.log

堆溢出现场保留

有些错误虽然不会导致 jvm 崩溃,但是对于服务而言也是非常严重的,比如stackOverflow、OutOfMemoryError,发生错误后,留存现场信息对分析错误原因是至关重要的。jvm 提供了保留堆溢出现场的方法,对于 JDK 8 而言,可能是 heap 溢出,也可能是 Metasapce 溢出。

-XX:HeapDumpPath=/Users/fengzheng/jvmlog

-XX:+HeapDumpOnOutOfMemoryError

最后出现异常后,保存的文件格式为 java_pidxxx.hprof,pid 后面是发生溢出的进程 id,之后可以用 VisualVM、JProfiler 等工具打开分析。

设置垃圾回收器类型

随着 JDK 版本的升级,可使用的垃圾收集器类型也越来越多了。JDK 8 可使用的垃圾收集器有 7 种,当然有点只适用于年轻代,有点只使用于老年代,JDK 8 中最新的垃圾收集器是 G1,可以用于年轻代和老年代。到了 JDK 11,还出了 ZGC。

下图是 JDK 8 中可使用的垃圾收集器以及它们配合使用的关系。

image

Serial、ParNew、Parallel Scavenge 只适用于年轻代,CMS、Serial Old、Parallel Old 只适用于老年代,而 G1 通用于年轻代和老年代。连线表示它们之间可配合使用的关系,其中 CMS 和 Serial Old 连线的意思是说 Serial Old 会作为 CMS 的后预案,当 CMS 发生 Concurrent Mode Failure 时启用。

在 JDK 8 中,如果不指定垃圾收集器,默认使用参数 -XX:+UseParallelGC,新生代使用 Parallel Scavenge,老年代使用 Serial Old。

-XX:+UseSerialGC:使用 Serial + Serial Old ,运行于 client 模式下的默认设置

-XX:+UseConcMarkSweepGC:使用 ParNew+CMS+Serial Old,CMS 垃圾收集器

-XX:+UseParallelGC:Parallel Scavenge + Serial Old,JDK 8 server 模式下的默认设置

-XX:+UseParallelOldGC:Parallel Scavenge + Parallel Old

-XX:+UseG1GC:使用 G1 垃圾收集器

开启远程 JMX 监控

除了日志外,当我们需要实时查看 JVM 运行情况的时候怎么办,当然可以到 JVM 所在服务器用 jstack、jmap、jinfo 等工具进行查看,但是又不够直观,这时候就需要开启 JMX 远程功能,使用 jConsole、VisualVM 等工具进行监控。或者自己开发监控平台,比如我之前就做了一个 web 版的简易 VisualVm。

开启参数如下:

-Dcom.sun.management.jmxremote

#指定 jvm 所在服务器 ip 或域名

-Djava.rmi.server.hostname=192.168.1.1

#指定端口

-Dcom.sun.management.jmxremote.port=9999

-Dcom.sun.management.jmxremote.rmi.port=9999

-Dcom.sun.management.jmxremote.authenticate=false

-Dcom.sun.management.jmxremote.ssl=false

最后

学习 Java 一段时间之后,想要进一步提升,JVM 是你永远绕不过去的,JVM 如何工作的,如何调优,将决定你和其他开发人员的差距。别等了,赶紧学吧。

java jvm 参数配置_Java 从小白到大牛,JVM 不得不知的一些参数和配置相关推荐

  1. 第68节:Java中的MYSQL运用从小白到大牛

    第68节:Java中的MYSQL运用从小白到大牛 前言 学习java必备要求,学会运用!!! 常见关系化数据库 BootStrap是轻量级开发响应式页面的框架,全局css组件,js插件.栅格系统是将页 ...

  2. 如何开启jvm日志_Java 从小白到大牛,JVM 不得不知的一些参数和配置

    推荐学习 阿里架构大牛说:JVM从入门到入魔,就是这么简单 性能优化专题复习:JVM+Tomcat+MySQL+面试+学习笔记等 神秘的 JVM 吗 有的同学虽然写了一段时间 Java 了,但是对于 ...

  3. python从小白到大牛百度云盘_Java从小白到大牛 (关东升著) 中文pdf+mobi版[36MB]

    <Java从小白到大牛>是一本Java语言学习立体教程,读者群是零基础小白,通过本书的学习能够成为Java大牛.主要内容包括:Java语法基础.Java编码规范.数据类型.运算符.控制语句 ...

  4. dockerfile tomcat 配置jvm参数_Java 从小白到大牛,JVM 不得不知的一些参数和配置

    神秘的 JVM 码 有的同学虽然写了一段时间 Java 了,但是对于 JVM 却不太关注.有的同学说,参数都是团队规定好的,部署的时候也不用我动手,关注它有什么用,而且,JVM 这东西,听上去就感觉很 ...

  5. java spring配置文件路径_java - 在spring b中从命令行设置活动配置文件和配置位置...

    java - 在spring b中从命令行设置活动配置文件和配置位置 我有一个春季启动应用程序. 我的应用程序中有三个配置文件 - > 开发,分期和生产. 所以我有3个文件 应用developm ...

  6. java创建oracle序列_java学习:Hibernate学习-用oracle sequence序列生成ID的配置示例

    接 SQ_TMP_EMP 这样运行时,Hibernate就会自动从SQ_TMP_EMP中取nextval用来填充到ID字段中 示例代码: 先创建一个工具类 package app; import or ...

  7. java spring mysql配置_java相关:mysql+spring+mybatis实现数据库读写分离的代码配置

    java相关:mysql+spring+mybatis实现数据库读写分离的代码配置 发布于 2020-4-4| 复制链接 分享一篇关于关于mysql+spring+mybatis实现数据库读写分离的代 ...

  8. java反射 获取参数类型_Java反射带参构造创建对象时如何自动转换参数类型

    需求是这样的:有一个类,类的路径知道,例如是com.xx.xx.xx其中有不同类型的成员变量(个数未知),有对应的setter和getter方法,有一个无参构造和一个全参构造.现在需要用反射机制... ...

  9. java 方法名相同_Java的方法的重载 :方法名相同,参数类型不同 - Break易站

    人类设计语言时,相同的词汇可以表达多种意思.而在Java里面,方法也被设计成这个模式,而区分这些相同方法名的就是方法的参数. Java的方法的重载的特点 方法的重载有下面的特点: 1. 方法名相同,参 ...

最新文章

  1. 学习java一定会用到的应用软件
  2. Java常用工具类---IP工具类、File文件工具类
  3. Ubuntu Linux配置Nginx+MySQL+PHP+phpMyAdmin详细步骤
  4. android最新知识点总结,学习android之 知识点总结
  5. Java泛型中extends和super的区别?
  6. JAVA-初步认识-第六章-类类型参数
  7. SQL Server 导入Excel数据
  8. GJB150.5A-2009军用装备实验室温度冲击环境试验
  9. SpringCloud 微服务视频教程
  10. jmeter进行http压力测试(图文小教程)
  11. rapidminer java_在Java应用程序RapidMiner的整合(Integration of RapidMiner i
  12. 各种单点登录方案调研
  13. 备份jar包的一些坑
  14. 便携智能音箱小问mini发布,李志飞:要做苹果一样的公司
  15. Python 编写24点游戏
  16. 基于stm32单片机的空气质量检测仿真(仿真+源码+全套资料)
  17. fhq-Treap题目记录
  18. 清华规划院 伟景行 诚聘 Jsp/Java/Web高级开发工程师 互联网开发主管 测试工程师 etc.
  19. 一文带你了解学习python的用处及好处,建议收藏
  20. 《Linux指令从入门到精通》——4.2 Linux下的简单文字模式文本编辑器

热门文章

  1. 免费阅读软件轻快阅读器怎么用
  2. 从零开始开发JVM语言(十一)Lambda
  3. Zigbee通讯漫谈(初次见面)
  4. 更改数据库对象所有者
  5. 最爱莫乎生命,其次是“你”
  6. 基于C语言STC89C52单片机电子密码锁的设计与仿真
  7. 菜鸟学exchange之一:exchange邮件系统的简单安装和部署
  8. 磁盘 io 的性能指标 简介
  9. linux socket关闭连接 shutdown与close
  10. mysql null 和 空字符串 区别