-
Notifications
You must be signed in to change notification settings - Fork 0
Description
欢迎来到 第十个 RebelLabs 备忘单!这次我们将专注于那些你想用但是忽略掉的 JVM 选项。在这篇文章中,我们将介绍每个重要选项的功能。但是首先,让我们回顾一下下面10份备忘录,就要追溯到2015年12月份了!
- ◻ Java 8 Best Practices
- ◻ Java 8 Streams
- ◻ Git Commands
- ◻ Docker Commands
- ◻ Java Collections
- ◻ SQL
- ◻ JUnit
- ◻ Spring Framework Annotations
- ◻ Java Generics
- ☑ JVM Options
我艹,太吊了(Wow, what a colorful journey! Here’s an amazing fact for you)。如果打印出上面所有的备忘录放在手边,那么你将腾出很多时间去做你喜欢的事。废话少说,点击下面的图片,打印出来吧,这样你就不用把那些该死的选项记在脑子里了。
让我们从上往下看。有三种类型的选项可以传递给 JVM:标准、非标准和高级选项。
- 如果使用高级选项,需要以
-XX:开头; - 使用非标准选项则是
-X; - 标准选项不需要追加任何东西。
我这样来告诉你,是不是发现好记了很多呢!下面,我们就从标准选项开始吧。
标准选项
如果你想获得所有的标准选项列表,只要在命令行输入 java 即可,不需要携带任何参数,你想看到大量的标准选型并且带有使用说明。在这份备忘单中,我们选了一些最有趣的选项。
这里附上我在执行 java 时的输出:
$ java
用法: java [-options] class [args...]
(执行类)
或 java [-options] -jar jarfile [args...]
(执行 jar 文件)
其中选项包括:
-d32 使用 32 位数据模型 (如果可用)
-d64 使用 64 位数据模型 (如果可用)
-server 选择 "server" VM
默认 VM 是 server,
因为您是在服务器类计算机上运行。
-cp <目录和 zip/jar 文件的类搜索路径>
-classpath <目录和 zip/jar 文件的类搜索路径>
用 : 分隔的目录, JAR 档案
和 ZIP 档案列表, 用于搜索类文件。
-D<名称>=<值>
设置系统属性
-verbose:[class|gc|jni]
启用详细输出
-version 输出产品版本并退出
-version:<值>
警告: 此功能已过时, 将在
未来发行版中删除。
需要指定的版本才能运行
-showversion 输出产品版本并继续
-jre-restrict-search | -no-jre-restrict-search
警告: 此功能已过时, 将在
未来发行版中删除。
在版本搜索中包括/排除用户专用 JRE
-? -help 输出此帮助消息
-X 输出非标准选项的帮助
-ea[:<packagename>...|:<classname>]
-enableassertions[:<packagename>...|:<classname>]
按指定的粒度启用断言
-da[:<packagename>...|:<classname>]
-disableassertions[:<packagename>...|:<classname>]
禁用具有指定粒度的断言
-esa | -enablesystemassertions
启用系统断言
-dsa | -disablesystemassertions
禁用系统断言
-agentlib:<libname>[=<选项>]
加载本机代理库 <libname>, 例如 -agentlib:hprof
另请参阅 -agentlib:jdwp=help 和 -agentlib:hprof=help
-agentpath:<pathname>[=<选项>]
按完整路径名加载本机代理库
-javaagent:<jarpath>[=<选项>]
加载 Java 编程语言代理, 请参阅 java.lang.instrument
-splash:<imagepath>
使用指定的图像显示启动屏幕
首先,我们从公共系统属性开始。这可以在 JVM 创建时传入,如下:
-Dblog=RebelLabs -D标志 表示后面的键值对将会作为JVM的系统属性,我们可以通过以下参数获取:
System.getProperty("blog"); //RebelLabs相同的系统属性,也可以在系统启动的时候通过程序创建,就像下面这样:
System.setProperty("blog", "RL");在 ZeroTurnaround,java agent 无非是我们的最爱!事实上,我们已经把它添加到了我们所有的产品中,从 JRebel 到 XRebel, 从 JRebel for Android 到 XRebel Hub!
java agent 非常像一个 JVM 插件,它使用了 Instrumentation API。通过它可以进行有趣的字节码操作,从而实现很多神奇的工具。要添加一个 java agent,只需指向一个包含 agent 代码和manifest 的jar包路径即可,如下:
-javaagent:/path/to/agent.jar如果想要的 JVM运行时获得更多其内部运行的信息,可以使用-verbose 选项。你可以使用多种风味来收集不同的信息。这些信息包括 加载类(class)、垃圾回收(gc)、JNI(jni)的活动信息。下面的例子中我们将获得 垃圾回收的详细信息。所有信息都将已日志的形式打印到标准输出中。
-verbose:gc非标准选项
像标准选项那样,你可以在命令行执行 java -X 召唤出完整的 非标准选项列表。下面附出我在本机执行的结果:
-Xmixed 混合模式执行 (默认)
-Xint 仅解释模式执行
-Xbootclasspath:<用 : 分隔的目录和 zip/jar 文件>
设置搜索路径以引导类和资源
-Xbootclasspath/a:<用 : 分隔的目录和 zip/jar 文件>
附加在引导类路径末尾
-Xbootclasspath/p:<用 : 分隔的目录和 zip/jar 文件>
置于引导类路径之前
-Xdiag 显示附加诊断消息
-Xnoclassgc 禁用类垃圾收集
-Xincgc 启用增量垃圾收集
-Xloggc:<file> 将 GC 状态记录在文件中 (带时间戳)
-Xbatch 禁用后台编译
-Xms<size> 设置初始 Java 堆大小
-Xmx<size> 设置最大 Java 堆大小
-Xss<size> 设置 Java 线程堆栈大小
-Xprof 输出 cpu 配置文件数据
-Xfuture 启用最严格的检查, 预期将来的默认值
-Xrs 减少 Java/VM 对操作系统信号的使用 (请参阅文档)
-Xcheck:jni 对 JNI 函数执行其他检查
-Xshare:off 不尝试使用共享类数据
-Xshare:auto 在可能的情况下使用共享类数据 (默认)
-Xshare:on 要求使用共享类数据, 否则将失败。
-XshowSettings 显示所有设置并继续
-XshowSettings:all
显示所有设置并继续
-XshowSettings:vm 显示所有与 vm 相关的设置并继续
-XshowSettings:properties
显示所有属性设置并继续
-XshowSettings:locale
显示所有与区域设置相关的设置并继续
-X 选项是非标准选项, 如有更改, 恕不另行通知。
以下选项为 Mac OS X 特定的选项:
-XstartOnFirstThread
在第一个 (AppKit) 线程上运行 main() 方法
-Xdock:name=<应用程序名称>"
覆盖停靠栏中显示的默认应用程序名称
-Xdock:icon=<图标文件的路径>
覆盖停靠栏中显示的默认图标当 JVM 启动的时候,它使用默认的 bootstrap 类路径来加载引导类和资源。要覆盖默认的启动类路径,可以通过以下选项把 路径 和/或 归档列表 提供给 JVM。
-Xbootclasspath:path你可以通过 -Xbootclasspath/a:path 和 -Xbootclasspath/p:path 分别追加或预加默认引导路径。
你是否厌烦了把 GC 事件作为日志输出到标准输出流?如果是,那么下面这个选项就是为你所准备!设置-Xloggc这个选项,并且提供一个你打算输出的目标文件路径!这个选项将会覆盖上节说到的-verbose:gc选项。
-Xloggc:filename避免 JVM 在堆中崩溃的最好做法 就是一开始就设置堆的大小。但问题是 堆应该设置为多大?这取决于你的应用程序和打算用JVM来做什么。在确定最终应该设置多大之前,你应该不断的改变你的堆大小然后进行测量评估。你可以设置堆的初始字节和最大字节数,单位可以使用常用的 k、m、g。下面的示例设置JVM的初始堆大小是 1GB,如果不够,最大能增长到 8GB。
-Xms1g -Xmx8g要禁用类的垃圾回收,可以用下面的选项。这样可以节省垃圾回收的时间,这时候只有对象才有资格被垃圾回收。当然,这样也增加了内存不足的风险,特别是在 使用了永久代空间的 Java 版本里。
-Xnoclassgc我们讨论的最后一个非标准选项,将允许你 profile 运行中的 JVM。当然,它没有那些具有 漂亮UI和丰富功能 的工具易于理解和使用,例如 XRebel (而且很便宜)。但是下面这个参数很容易启用。所有的信息都会在标准输出显示。
-Xprof这个备忘单由 XRebel 提供,它是一个在你工作中 提醒你的应用性能问题的工具,而不是让你的用户来发现这些问题。如果你正在开发 Java Web 程序,就应该尝试使用它。这个将会改变你对你程序表现的态度。
高级选项
行为(Behavior)
我们将围绕着垃圾回收这个主题开始。在 Java9 中,标准的垃圾回收器是 Garbage First Garbage Collector (G1GC),你也可以选择其它的垃圾回收器来执行垃圾回收策略。这些垃圾收集器包括 并发标记清除(Concurrent Mark Sweep (CMS))、并行扫描、串行 垃圾回收器,当然还包括G1GC。你可以通过下选项来启动它们。无需多说,请不要尝试同时使用多个选项来运行。
-XX:+UseConcMarkSweepGC
-XX:+UseParallelGC
-XX:+UseSerialGC
-XX:+UseG1GC飞行记录器这(Flight Recorder)个功能是 JDK 内置的。它允许你获得有关应用和JVM的详细信息。和你期望的分析器功能类似,它将收集事件信息供你检查。为了使用这个功能,你需要使用单独的选项来解锁JVM的这个商业功能。这两个选项如下所示:
-XX:+FlightRecorder -XX:+UnlockCommercialFeatures调试(Debugging)
如果你希望用一个专门的文件来查看错误数据,可以使用下面的选项 外加一个日志文件名。现在你就可以看到一个漂亮干净的日志文件,里面只有那些令人惊讶的错误!
-XX:ErrorFile=file.log想调试一个错误,但是却没有错误信息,没有什么比这个更令人沮丧了。最好的例子例子就是 常见的OutOfMemory错误。这个事件会让你的JVM瘫痪却不告诉你原因。使用下面这个选项可以帮到你。HeapDumpOnOutOfMemory 会为你提供一个包含大量调试信息的 .hprof 文件。你可以使用 Eclipse MAT 或者其他你喜欢的工具打开,它可以找出是什么囤积在堆里面。里面内容非常详细,你可以拿到最原始的对象,诊断出可能的内存泄露问题。
-XX:+HeapDumpOnOutOfMemory如果你很想了解垃圾回收器如何工作,但是又不想使用-verbose:gc 打印沉长的完整详细信息,可以尝试 PrintGC 选项。每次执行垃圾回收时,它只简单的打印一条消息。
-XX:+PrintGC你对 什么时候 或 在什么条件下 你的类会被加载充满好奇吗?如果是,你可能需要看一下下面这个选项。这个选项可以追踪JVM加载的每个类。如果这种事情对你是有帮助的。
-XX:+TraceClassLoading性能(Performance)
在你打算发牢骚之前声明一下,是的,我知道 永久代已经从 Java8 中移除了!但是,如果没有酷到使用最新版的版本,你会发现下面的这个参数很有用。如果你存在 PermGen 不够的问题,那么你会发现它很有用。你可以改变 PermGen 的最大大小,就像改变老年代堆大小一样。只需要提供你想要的最大字节数,如下:
-XX:MaxPermSize=512k你应该知道线程的栈内存空间并没有从堆中分配,因此当你使用 -Xms 和 -Xmx 选项的时候并不会对此产生影响。如果你想增加 甚至是减少线程栈空间大小,你可以像下面这样指定一定的字节数。
-XX:ThreadStackSize=256k在 Java8 之前提供了一个有趣的UseStringCache 选项。这允许JVM缓存字符串。然而不幸的是它从 Java8 中移除了,而且没有可替换的选项。所以如果你想用到这个选项必须使用较早的版本。
-XX:+UseStringCache如果你正在使用 G1GC,你应该非常熟悉这个区域的大小,并且了解什么是对你的应用有益。与所有的选项一样,你应该不断的尝试不同的值,然后进行评估。将来,G1GC 将成为 Java9 的标配,你需要和它成为最好的朋友。
-XX:G1HeapRegionSize=4m我们之前提到的-Xms 和 -Xmx选项只适用于老年代堆。在大多数JVM中,Java 的堆空间还包含一个 年轻代 或者 托儿所(nursery) 堆。要设置年轻代的最大大小,可以使用一下选项。
-XX:MaxNewSize=256m如果你想让你的 JVM 性能很激进(angry and thirsty)的战斗,你可以使用下面这个 积极的性能优化功能。
XX:+AggressiveOpts总结
这篇文章文章中,我们涵盖了一些流行并且有趣的 Java 命令行选项。对于完整的 Java8选项列表,请查看 Oracle 官方文档。当你修改你的参数的时候,请务必记住,一定要不断的 测试、评估、迭代,以便正确的调优 JVM,尤其是在堆大小方面。
困惑
-Xms 和 -Xmx
原文在讲到 -XX:MaxNewSize=256m 这个参数的时候,说 -Xms 和 -Xmx 修改的是老年代的堆空间大小,感觉不是太对,因为印象中,这两个参数设置的是整个堆空间的大小,包含 新生代(年轻代)和旧生代(老年代)。
后续查了一下Oracle Garbage Collection Tuning Guide 官方文档中Total Heap这一节,
文中提到
the total size is bounded below by
-Xms<min>and above by-Xmx<max>.
所以-Xms 和 -Xmx修改的是整个堆的大小,而不仅仅是老年代。