JVM总结

该文档主要介绍JVM内存管理模型,垃圾回收算法,常用GC参数,JVM调优四部分内容。

一,内存管理模型

JVM将其使用的内存划分为如下几个区域:

    • 本地方法站(native方法栈)
    • 虚拟机栈(方法栈)
    • 程序计数器(当前线程位置)
    • Perm(运行时常量池,静态方法,class对象等)
  1. 堆 
    • Young
      • Eden
      • S0
      • S1:S1与S0相同大小
    • Old

大而言之其实就是两个部分:栈,堆。栈上空间一般都隶属各个线程(方法区,常量池线程共享),意思是每个线程有自己的栈空间,其上主要是一些原始类型变量。堆区负责存放对象,因为这些对象90%都是短命对象,所以按照对象的生命长度将堆区划分为短命堆区(年轻代),和长命堆区(年老代)。

二,垃圾回收算法

 有了上面按照不同的生命周期来划分的区域,所以JVM也有了按照生命周期来回收垃圾对象。

垃圾对象:没有被根引用的对象

Young代回收算法:

因为Young代都是短命对象,一次YoungGC会回收大部分对象,只有少量会剩下来。ParNew采用多线程,Stop The World的方式,采用复制算法进行回收。

特点是:

  1. Stop The Workd
  2. 多线程并发回收
  3.  复制算法,内存回收后方便分配

Old代采用CMS回收算法:

 回收步骤:

  1. 初始化清除:Stop The World 标记由根可以直达的对象
  2. 并发标记:并发标记可达对象
  3. 重新标记:Stop The World并发查找前一阶段新生代晋升或者新分配,被更新的对象
  4. 并发清理
  5. 线程重置

优点:

  • 低延迟

缺点:

  • 因为是基于标记清除,容易产生碎片 

三,常用GC参数

JVM parameters in Java

我们根据JVM参数以-X开头或-XX开头将JVM参数分成两个部分:

1) 以-X开头的都是非标准的(这些参数并不能保证在所有的JVM上都被实现),而且如果在新版本有什么改动也不会发布通知。

2)以-XX开头的都是不稳定的并且不推荐在生产环境中使用。这些参数的改动也不会发布通知。

 


对响应时间要求很高的系统来说,良好掌握JVM关于GC调优的参数是很重要的。比如一个高流量低延迟的电子交易平台,他要求的响应时间都是毫秒级的。要获得适合的参数组合需要大量的分析和不断的尝试,更依赖于交易系统的特性。

关于JVM选项的几点:

1) 布尔型参数选项:-XX:+ 打开, -XX:- 关闭。(比如-XX:+PrintGCDetails)

2) 数字型参数选项通过-XX:<名称>=<设定>。数字可以是 m/M(兆字节),k/K(千字节),g/G(G字节)。比如:32K表示32768字节。(比如-XX:-XX:NewRatio=4)

3) 字符行参数选项通过-XX:<名称>=<设定>,通常用来指定一个文件,路径,或者一个命令列表。(比如-XX:HeapDumpPath=./java_pid.hprof)

命令 java -help可以列出java 应用启动时标准选项(不同的JVM实现是不同的)。java -X可以列出不标准的参数(这是JVM的扩展特性)。-X相关的选项不是标准的,被改变也不会通知。如果你想查看当前应用使用的JVM参数,你可以使用:ManagementFactory.getRuntimeMXBean().getInputArguments()。

下面就是经常用到的JVM参数列表。


1) 跟 Java 堆大小相关的 JVM 内存参数

下面三个 JVM 参数用来指定堆的初始大小和最大值以及堆栈大小
 -Xms        设置 Java 堆的初始化大小
 -Xmx       设置最大的 Java 堆大小
 -Xss        设置Java线程堆栈大小
 -Xmn       设置新生代空间大小
-------------------------------------------------

2) 关于打印垃圾收集器详情的 JVM 参数

 -verbose:gc 记录 GC 运行以及运行时间,一般用来查看 GC 是否是应用的瓶颈

 -XX:+PrintGCDetails 记录 GC 运行时的详细数据信息,包括新生成对象的占用内存大小以及耗费时间等

 -XX:-PrintGCTimeStamps  打印垃圾收集的时间戳

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

3) 设置 Java 垃圾收集器行为的 JVM 参数

-XX:+UseParallelGC      使用并行垃圾收集

-XX:-UseConcMarkSweepGC 使用并发标志扫描收集 (Introduced in 1.4.1)

-XX:-UseSerialGC        使用串行垃圾收集 (Introduced in 5.0.)

需要提醒的是,但你的应用是非常关键的、交易非常频繁应用时,应该谨慎使用 GC 参数,因为 GC 操作是耗时的,你需要在这之中找到平衡点。 
-------------------------------------------------

4)JVM调试参数,用于远程调试

-Xdebug -Xnoagent -Xrunjdwp:transport=dt_socket,server=y,suspend=n,address=8000

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

5) 关于性能诊断的 JVM 参数

-Xprof

-Xrunhprof
-------------------------------------------------

6) 关于类路径方面的 JVM 参数

-Xbootclasspath用来指定你需要加载,但不想通过校验的类路径。JVM 会对所有的类在加载前进行校验并为每个类通过一个int数值来应用。这个是保证 JVM 稳定的必要过程,但比较耗时,如果你希望跳过这个过程,就把你的类通过这个参数来指定。
-------------------------------------------------

7) 用于修改 Perm Gen 大小的 JVM 参数

下面的这三个参数主要用来解决 JVM 错误: java.lang.OutOfMemoryError:Perm Gen Space.
-XX:PermSize and -XX:MaxPermSize
-XX:NewRatio=2  Ratio of new/old generation sizes.
-XX:MaxPermSize=64m     Size of the Permanent Generation.
-------------------------------------------------

8) 用来跟踪类加载和卸载的信息

-XX:+TraceClassLoading和 -XX:+TraceClassUnloading 用来打印类被加载和卸载的过程信息,这个用来诊断应用的内存泄漏问题非常有用。

-------------------------------------------------
9) JVM switches related to logging

-XX:+TraceClassLoading and -XX:+TraceClassUnloading print information class loads and unloads. Useful for investigating if you have a class leak or if old classes (like JITed Ruby methods in JRuby) are getting collected or not.You can read more about logging in Java on my post 10 Tips while logging in Java

-XX:+PrintCompilation prints out the name of each Java method Hotspot decides to JIT compile. The list will usually show a bunch of core Java class methods initially, and then turn to methods in your application. In JRuby, it eventually starts to show Ruby methods as well
-------------------------------------------------

10)用于调试目的的 JVM 开关参数

-XX:HeapDumpPath=./java_pid.hprof  Path to directory or file name for heap dump.

-XX:-PrintConcurrentLocks       Print java.util.concurrent locks in Ctrl-Break thread dump.

-XX:-PrintCommandLineFlags   Print flags that appeared on the command line. 

 下面贴一份我们项目中用到的JVM参数(4core,8G):

 1 /usr/local/java/bin/java -server -Dapp.key=api -Dfile.encoding=UTF-8 -Dsun.jnu.encoding=UTF-8 -Djava.io.tmpdir=/tmp
 2 
 3 -Djava.net.preferIPv6Addresses=false
 4 
 5 -Xmx4g -Xms4g -Xmn2g -XX:PermSize=128m
 6 
 7 -XX:+UseConcMarkSweepGC -XX:+CMSParallelRemarkEnabled
 8 
 9 -XX:+ExplicitGCInvokesConcurrent -XX:CMSInitiatingOccupancyFraction=70
10 
11 -XX:+UseCMSInitiatingOccupancyOnly -XX:+CMSClassUnloadingEnabled
12 
13 -XX:+TieredCompilation -XX:CICompilerCount=4
14 
15 -XX:+PrintGCDetails -XX:+PrintHeapAtGC -XX:+PrintTenuringDistribution -XX:+PrintGCTimeStamps -XX:+PrintGCDateStamps -Xloggc:/opt/logs/mobile/groupapi/groupapi.gc.log -XX:ErrorFile=/opt/logs/mobile/groupapi/groupapi.vmerr.log
16 
17 -XX:HeapDumpPath=/opt/logs/mobile/api/api.heaperr.log -Djetty.home= -Djetty.appkey=api
18 
19 -Djetty.context=/ -Djetty.logs=/opt/logs/mobile/groupapi -Djetty.webroot=/opt/meituan/mobile/api/webroot com.sankuai.mms.boot.Bootstrap 

四,JVM调优

 

posted @ 2015-10-21 11:35  欣欣王  阅读(2733)  评论(0编辑  收藏  举报