本文主要参考自《深入理解 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. Javascript和jquery事件--鼠标滚轮事件WheelEvent

    <1>js事件 滚轮事件在js中,不同浏览器还是有不同的,介于我只测试谷歌和火狐浏览器的情况,其他浏览器有待自行探索.有三种写法: target.onmousewheel = wheel; ...

  2. zookeeper分布式协调服务的使用一

    Zookeeper是一个高性能,分布式的应用协调服务. 提供服务: 1.集群成员的管理(Group Membership) 2.分布式锁(Locking) 3.选主(Leader Election) ...

  3. 每日技术总结:filter(),Bscroll

    前言: 这是一个vue的电商项目,使用express后端提供数据. 1.filter()函数. 事情是这样的.我从数据库拿到了所有分类数据. 分类有三个等级.父类,子类,孙类这样.但它们都在同一张表里 ...

  4. C标签的使用.md

    <c:set> 设置变量 <c:set var="a" scope="request" value="${'www'}"/ ...

  5. [CSS] Control Image Aspect Ratio Using CSS

    Resize images and videos to fill their parent and maintain their aspect ratio with pure CSS. The new ...

  6. putty-gns3

    hcl-cloud用的就是这个putty http://forum.gns3.net/topic5016.html File comment: Compiled PuTTY 0.62 for wind ...

  7. 从Lua调用C

    从Lua调用C: 方式:C函数从栈中获取函数參数(第一个參数总是局部栈的索引1),将结果压入栈中,C函数须要返回结果数量. 每一个函数都有自己的局部私有栈 样例: static int l_sin(l ...

  8. 应用层协议实现系列(三)——FTPserver之设计与实现

    在实现了HTTPserver之后.本人打算再实现一个FTPserver. 因为FTP协议与HTTP一样都位于应用层,所以实现原理也类似. 在这里把实现的原理和源代码分享给大家. 首先须要明白的是FTP ...

  9. RSA公钥、私钥、签名和验签

    1 RSA加密算法介绍 RSA又叫非对称加密算法,这类加密算法有一对秘钥,其中一个用来加密一个用来解密.这一对秘钥中你可以选择一个作为私钥(自己保存),另一个作为公钥(对外公开).用私钥加密的内容只能 ...

  10. jquery平滑滚动页面

    滚动到顶部 $('.scroll_top').click(function(){$('html,body').animate({scrollTop: '0px'}, 800);}); 滚动到指定位置 ...