本文主要参考自《深入理解 Java 虚拟机》。这本书是国人写的难得的不是照搬代码注释的且不是废话连篇的技术书,内容涵盖了 Java 从源码到字节码到执行的整个过程,包括了 JVM(Java Virtual Machine)的架构,垃圾收集的介绍等。这里摘录出关于配置 JVM 基本参数来调优 Eclipse 启动的过程,比较初级,供初学者参考。

基础知识

针对 JVM 的参数调优主要集中在数据区大小的控制和垃圾回收策略的选择。关于 JVM 运行机制等更多内容可参考其他博文

JVM 的运行时数据区

运行时 JVM 的数据区主要包括各线程私有的栈和程序计数器,线程共享的方法区,以及管理对象的堆(又称回收堆)等。程序运行时,类信息、常量、静态变量等会被加载到方法区。运行过程中几乎所有对象都在堆里,内存占用的空间最大,这也是最值得优化得部分。

JVM 的垃圾回收策略

Java 程序中,除了基本类型(primitive types),其他的数据都是以对象的形式存在。对象生命周期有长有短,如果无区别的保留在内存中,会造成内存超载。内存垃圾回收(Garbage Collection, 缩写 GC)就是解决这一问题的策略。

注意:JVM 不仅仅只对对象进行垃圾回收,实际上也会对废弃常量和无用的类做回收。

垃圾回收首先得找到需要被回收的对象,一般采用根搜索算法来标记处这些过时的对象(另外有一种简单的实现:引用计数,但存在明显的弊端,即循环引用)。

回收垃圾的过程会消耗计算资源和时间。根据不同的处理方式,垃圾回收有不同的策略,现在常用的是分代收集算法:根据对象的存活周期将堆划分为几代:新生代(Young Generation 或 New Generation)和老生代(Tenured Generation),HotSpot 虚拟机里还分出了永生代(基本等同于方法区)。不同代采用不同的垃圾回收策略。

HotSpot 虚拟机

HotSpot 虚拟机中,Perm 代指永生代,Old 代指老年代,而新生代使用复制算法,将区域划分为三块:Eden,S0 和 S1(S 是 Survivor 的缩写)。

IBM 研究表明,新生代中的对象 98%是朝生夕死的,三者的比例划分是 8:1:1。对象先分配到 Eden,如果 Eden 中内存占用量达到一定得比例,触发 Minor GC,JVM 会将 Eden 和 S0(或 S1)中存活的对象复制到 S1(或 S0),并清空 Eden 和 S0(或 S1)。如果同时老年代的内存占用量打达到一定比例,会触发 Major GC(也称 Full GC)。通常 Major GC 比 Minor GC 慢 10 倍以上。

编译过程

Java 一直号称“Write once, run anywhere”,这个特性正是由 JVM 这一虚拟层来支撑的。

Java 源代码首先编译为 Java 字节码,字节码再被 JVM 加载运行。运行的过程可以是直接针对字节码的解释执行,也可以是经过了 JIT(Just in time)编译为机器码后的执行。另外,还有静态提前编译器(Ahead Of Time,也缩写为 AOT),能将源码直接编译为机器码。

HotSpot 虚拟机的 JIT 编译器有:Client Complier(简称 C1)、Server Complier(简称 C2)以及在 Java7 中堆出的分层编译器。C1 编译器做一些快速的优化,C2 做一些更耗时的优化但是产生更高效的代码,而分层编译器则结合了两者的优点:快速的启动和逐步的优化(brings client startup speeds to the server VM)。

性能监控和故障处理工具

对于系统调优和问题定位,周志明在《深入 Java 虚拟机》中总结到

给一个系统定位问题的时候,知识、经验是关键基础,数据是依据,工具是运用知识处理数据的手段。这里说的数据包括:运行日志、异常堆栈、GC 日志、线程快照、堆转储快照等……应当意识到工具永远都是知识技能的一层包装,没有什么工具是“秘密武器”。

Java 提供了很多工具给开发者来监控和处理运行中的问题。包括命令行工具以及可视化工具

命令行工具

比如 jps, jstat, jinfo 等。举例如下:

1
2
3
jstat -gcutil xxx #xxx 是 jps 查出的 LVMID,查看 gc 相关数据
jstat -gccause xxx#查看 gc 的原因
jinfo -flag XXX xxx#XXX 是参数名,xxx 是 VMID,查看虚拟机的参数值

可视化工具

  • JConsole:比较老得分析软件,Java 自带。Windows 下搜 jconsole.exe,Mac 下启动命令为 jconsole
  • Eclipse Memory Analyzer Tool:用于分析 dump 下的堆数据
  • VisualVM:推荐,很全能的分析工具

JVM 参数

这里零散的罗列了一些我用到的简单的 JVM 配置参数:

内存大小控制:

  • -Xmx20M: 堆的最大值
  • -Xms10M: 堆的初始分配内存
  • -Xmn: 新生代堆的分配内存
  • -Xss128k: 线程的栈空间大小
  • -XX:PermSize=10M | 方法区初始大小
  • -XX:MaxPermSize=10M |方法区最大值

编译相关:

  • -Xint: 关闭 JIT,完全使用解释执行,实践中没什么作用,解释执行很慢。
  • -client: 启动 C1 编译器
  • -server: 启动 C2 编译器
  • -XX:+TieredCompilation: 启动分层编译器

其他:

  • -XX:+DisableExplicitGC: 屏蔽 System.gc()调用
  • -PrintGCDetails: 让 jvm 在每次发生 gc 的时候打印日志,利于分析 gc 的原因和状况
  • -XX:+HeapDumpOnOutOfMemoryError: 内存溢出时 dump 下 heap,可以通过 Eclipse Memory Analyzer Tool 打开查看。
  • -XX:HeapDumpPath=/: dump 下的 heap 文件快照的路径。Eclipse 中默认放到项目的根目录中
  • -XVerify:none: 禁止字节码验证

调优 Eclipse 启动的实践

实践环境

  • CPU: 2.8 GHz Intel Core i7
  • 内存: 8 GB 1333 MHz DDR3
  • 操作系统: OS X 10.9.1(64bits)
  • Eclipse:Version: Kepler Service Release 1, Build id: 20130919-0819
  • Java:java version “1.7.0_45”

调优实践

调优 Eclipse 启动实际上就是调优 Eclipse 在 JVM 中的加载和程序启动阶段的运行。由于默认的 Ecpise 启动配置无法适应所有不同的硬件、软件环境,做针对性的调优是必要的。

Eclipse 的启动配置文件是 eclipse.ini,对 JVM 的参数调优直接在该文件中修改。OS X 下,其文件路径为 $ECLIPSE/Eclipse.app/Contents/MacOS/eclipse.ini(注意不是 Eclipse 文件包根目录下得 eclipse.ini)。

测 Eclipse 启动时间

要优化 Eclipse 的启动时间,先要能确定 Eclipse 的启动时间。这里推荐网友实现的一个 Eclipse 插件:计算启动时间的 Eclipse 插件。下载后放到 Eclipse 的插件包中,启动 Eclipse 即可看到弹窗显示的启动时间。为了得到一个尽可能公平的测试结果,需要在测试过程中关闭其他程序,避免 CPU 负载带来的误差,并多次测试取平均值。

调优策略

使用 VisualVM 查看程序的运行状况来定位瓶颈,尝试调优解决。下图是 VisualVM 的示例图,右边图示展示了 GC 的状态以及编译时间、类加载时间和垃圾回收时间等指标。

也可以通过命令行工具查看 GC 的状态,比如:jstat -gc XXX #其中 XXX 是 jps 查出的进程的 LVMID.

我的实践总结如下:

  • 类加载时间过长:禁止加载类时的字节码验证。我们认为 Eclipse 的字节码是可靠的。-XVerify:none
  • 编译时间:-client缩短了编译时间,但长期运行的性能可能受影响,-server编译时间长,而编译优化做得更多,后期使用汇报大,-XX:+TieredCompilation分层编译则集合了前两者的优势。没有特殊需求,可选用这一编译选项。
  • Minor GC 次数太多:新生代空间太小,加大新生代的内存大小。-Xmn800m,同时,增大回收堆的总大小上限(-Xmx1024m)。
  • Full GC 次数太多:为了避免回收堆由小到大的动态增长增加时间开销,可将其初始大小跟最大上限设定为同一值-Xms1024m,并增加老年代的大小(-XX:PermSize=256m-XX:MaxPermSize=256m)。
  • 代码中的 GC 调用:Eclipse 代码中有 System.GC()的调用可能促使 JVM 执行垃圾回收,可以通过-XX:+DisableExplicitGC来防止。
  • 垃圾收集器的选择:垃圾收集器有很多,比如 Serial、ParNew、Parallel Scavenge、CMS、G1 等。推荐使用老生代 CMS 新生代 ParNew 的组合来应对 Eclipse 用户交互频繁的情况(-XX:+UseParNewGC-XX:+UserConcMarkSweepGC)。同时提升 CMS 的垃圾回收的触发条件:-XX:CMSInitiatingOccupancyFraction=85,进一步降低 Full GC 的出现。

最终 eclipse.ini

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
-startup
../../../plugins/org.eclipse.equinox.launcher_1.3.0.v20130327-1440.jar
--launcher.library
../../../plugins/org.eclipse.equinox.launcher.cocoa.macosx.x86_64_1.1.200.v20130807-1835
-product
org.eclipse.epp.package.standard.product
--launcher.defaultAction
openFile
-showsplash
org.eclipse.platform
--launcher.XXMaxPermSize
256m
--launcher.defaultAction
openFile
--launcher.appendVmargs
-vmargs
-Dosgi.requiredJavaVersion=1.6
-XstartOnFirstThread
-Dorg.eclipse.swt.internal.carbon.smallFonts
-Xms1024m
-Xmx1024m
-Xmn800m
-Xdock:icon=../Resources/Eclipse.icns
-XstartOnFirstThread
-Dorg.eclipse.swt.internal.carbon.smallFonts
-XX:+TieredCompilation
-XX:PermSize=256m
-XX:MaxPermSize=256m
-XX:+DisableExplicitGC
-XVerify:none
-XX:+UseParNewGC
-XX:+UserConcMarkSweepGC
-XX:CMSInitiatingOccupancyFraction=85

其他参考

 原文地址:http://biaobiaoqi.me/blog/2014/01/17/java-performance-tunning-in-practice/
 版权声明:自由转载-非商用-非衍生-保持署名| Creative Commons BY-NC-ND 3.0

JVM参数调优:Eclipse启动实践的更多相关文章

  1. JVM参数调优

    JVM参数调优 JVM参数调优是一个很头痛的问题,可能和应用有关系,下面是本人一些调优的实践经验,希望对读者能有帮助,环境LinuxAS4,resin2.1.17,JDK6.0,2CPU,4G内存,d ...

  2. (转)JVM参数调优八大技巧

    这里和大家分享一下JVM参数调优的八条经验,JVM参数调优,这是很头痛的问题,设置的不好,JVM不断执行FullGC,导致整个系统变得很慢,网站停滞时间能达10秒以上,相信通过本文的学习你对JVM参数 ...

  3. 性能测试三十六:内存溢出和JVM常见参数及JVM参数调优

    堆内存溢出: 此种溢出,加内存只能缓解问题,不能根除问题,需优化代码堆内存中存在大量对象,这些对象都有被引用,当所有对象占用空间达到堆内存的最大值,就会出现内存溢出OutOfMemory:Java h ...

  4. 【学习】011 JVM参数调优配置

    自动内存管理机制 Java虚拟机原理 所谓虚拟机,就是一台虚拟的机器.他是一款软件,用来执行一系列虚拟计算指令,大体上虚拟机可以分为 系统虚拟机和程序虚拟机, 大名鼎鼎的Visual Box.Vmar ...

  5. SpringBoot-内部运行jvm参数调优

    SpringBoot JVM参数调优 这个根据服务器的内存大小,来设置堆参数. -Xms :设置Java堆栈的初始化大小 -Xmx :设置最大的java堆大小 实例参数-XX:+PrintGCDeta ...

  6. Java后端进阶-JVM参数调优

    package com.study.performance; import org.springframework.boot.SpringApplication; import org.springf ...

  7. JVM参数调优总结

    一.前言 要想成为一名高级Java开发具备JVM调优的能力必不可少,能够根据项目实际情况进行JVM调优的前提是理解JVM原理和常用JVM参数的含义及作用,虽然<深入理解Java虚拟机>这本 ...

  8. jvm 参数调优

    FROM: http://www.cnblogs.com/redcreen/archive/2011/05/04/2037057.html#CMSInitiatingOccupancyFraction ...

  9. JVM 参数调优配置

    在 tomcat 配置文件 tomcat/bin/catalina.sh 中 配置  JAVA_OPTS="-server -Xms2048m -Xmx2048m -Xss1024K -XX ...

随机推荐

  1. HTTP网络协议(三)

    HTTP首部字段有四种类型:通用首部字段,请求首部字段,响应首部字段,实体首部字段.  通用首部字段: 首部字段 说明 Cache-Control 控制缓存的行为 Connection 逐跳首部.连接 ...

  2. 汉字的ascii

  3. Spring Boot使用模板freemarker【从零开始学Spring Boot(转)

    视频&交流平台: à SpringBoot网易云课堂视频 http://study.163.com/course/introduction.htm?courseId=1004329008 à  ...

  4. js课程 5-13 js事件绑定和鼠标事件注意事项有哪些

    js课程 5-13  js事件绑定和鼠标事件注意事项有哪些 一.总结 一句话总结:js代码的灵魂就是改变标签的属性和样式,就这两种. 1.js触发改的东西是哪两样? 属性和样式 2.js如何让页面用标 ...

  5. 37、mipg-streamer的使用讲解

    讲解mjpg-streamer 其功能: 1.控制摄像头采集数据(通过ioctl采集数据,所有不支持CMOS,CMOS之前写驱动的时候是通过read,所有需要修改mjpg-streamer的源码或者C ...

  6. 中间件、服务器和Web服务器三者的区别

    相信很多的Web安全初学者和我一样,对中间件和服务器的认识不够深刻,对两者的概念可能会有所混淆. 正好今天在学习的时候突然想到了这个问题,粗略百度了一下,似乎网上对这个问题的解释不多,那么就由我来为大 ...

  7. 【z02】选择客栈

    (hotel.cpp/c/pas) [问题描述] 丽江河边有n 家很有特色的客栈,客栈按照其位置顺序从 1 到n 编号.每家客栈都按照 某一种色调进行装饰(总共 k 种,用整数 0 ~ k-1 表示) ...

  8. 一次性能优化将filter转换

    有一条SQL性能有问题,在运行计划中发现filter.遇到它要小心了,类似于nestloop.我曾经的blog对它有研究探索运行计划中filter的原理.用exists极易引起filter. 优化前: ...

  9. 6、linux中同步、互斥、阻塞(原子操作、信号量、阻塞)

    1. 原子操作原子操作指的是在执行过程中不会被别的代码路径所中断的操作.常用原子操作函数举例:atomic_t v = ATOMIC_INIT(0);     //定义原子变量v并初始化为0atomi ...

  10. 20、RTC驱动程序

    drivers\rtc\rtc-s3c.c s3c_rtc_init platform_driver_register s3c_rtc_probe rtc_device_register(" ...