JVM 垃圾回收器与参数配置

JVM 垃圾回收器与参数配置

JVM参数概述

详见:http://docs.oracle.com/javase/8/docs/technotes/tools/unix/java.html

主要分为以下几类:

主要有标准参数(java -help) 和 非标准参数(java -X)还有以XX开头的非标准参数(Advanced Runtime Options)。

1)标准参数

These are the most commonly used options that are supported by all implementations of the JVM.

可以通过 java -help 命令列出。

2) 非标准参数(Non-Standard Options)

These options are general purpose options that are specific to the Java HotSpot Virtual Machine.

可以通过java -X 命令列出。

➜  ~ 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 选项是非标准选项, 如有更改, 恕不另行通知。

比较常用的两个参数   

-Xms<size>        设置初始 Java 堆大小

-Xmx<size>        设置最大 Java 堆大小

3)以XX开头的非标准参数(Advanced Runtime Options)

These options control the runtime behavior of the Java HotSpot VM.

所有的XX参数都以”-XX:”开始,但是随后的语法不同,取决于参数的类型。

  1. 对于布尔类型的参数,我们有”+”或”-“,然后才设置JVM选项的实际名称。例如,-XX:+option 用于启用选项,而-XX:-option用于关闭选项。
  2. 对于需要非布尔值的参数,如string或者integer,我们先写参数的名称,后面加上”=”,最后赋值。例如, -XX:option=值。

 

Java demo

package com.rocketmq.jvmtest;

public class JvmTestMain01 {
    public static void main(String[] args) {
        //=====================Begin=========================
        System.out.print("Xmx=");
        System.out.println(Runtime.getRuntime().maxMemory() / 1024.0 / 1024 + "M");

        System.out.print("free mem=");
        System.out.println(Runtime.getRuntime().freeMemory() / 1024.0 / 1024 + "M");

        System.out.print("total mem=");
        System.out.println(Runtime.getRuntime().totalMemory() / 1024.0 / 1024 + "M");

        //=====================First Allocated=========================
        System.out.println("5MB array allocated");
        byte[] b1 = new byte[5 * 1024 * 1024];
        //=====================First Allocated end=========================

        System.out.print("Xmx=");
        System.out.println(Runtime.getRuntime().maxMemory() / 1024.0 / 1024 + "M");

        System.out.print("free mem=");
        System.out.println(Runtime.getRuntime().freeMemory() / 1024.0 / 1024 + "M");

        System.out.print("total mem=");
        System.out.println(Runtime.getRuntime().totalMemory() / 1024.0 / 1024 + "M");

        //=====================Second Allocated=========================
        System.out.println("10MB array allocated");
        byte[] b2 = new byte[10 * 1024 * 1024];
        //=====================Second Allocated end=========================

        System.out.print("Xmx=");
        System.out.println(Runtime.getRuntime().maxMemory() / 1024.0 / 1024 + "M");

        System.out.print("free mem=");
        System.out.println(Runtime.getRuntime().freeMemory() / 1024.0 / 1024 + "M");

        System.out.print("total mem=");
        System.out.println(Runtime.getRuntime().totalMemory() / 1024.0 / 1024 + "M");

        //=====================OOM=========================
        System.out.println("OOM!!!");
        System.gc();
        byte[] b3 = new byte[40 * 1024 * 1024];
    }
}

shell 脚本

#!/bin/sh

error_exit ()
{
    echo "ERROR: $1 !!"
    exit 1
}
# -e filename 表示文件是否存在
# $HOME 取默认的环境变量 HOME 变量
[ ! -e "$JAVA_HOME/bin/java" ] && JAVA_HOME=$HOME/jdk/java
[ ! -e "$JAVA_HOME/bin/java" ] && JAVA_HOME=/usr/java
[ ! -e "$JAVA_HOME/bin/java" ] && error_exit "Please set the JAVA_HOME variable in your environment, We need java(x64)!"

# 通过 export 命令导出到全局环境变量中
# ${var} 返回变量值 推荐这种写法 可以使代码的可读性更好避免歧义
# $(dirname $0) 返回这个脚本文件放置的目录
# export BASE_DIR=$(dirname $0)/.. 设置BASE_DIR为脚本文件放置的目录的上级目录
# 比如 cd ./..  返回上级目录
export JAVA_HOME
export JAVA="$JAVA_HOME/bin/java"
export BASE_DIR=$(dirname $0)/..
export CLASSPATH=.:${BASE_DIR}:${CLASSPATH}

#===========================================================================================
# JVM Configuration
#  -Xms<size>        设置初始 Java 堆大小
#  -Xmx<size>        设置最大 Java 堆大小
#  -Xmnsize Sets the initial and maximum size (in bytes) of the heap for the young generation (nursery).
#===========================================================================================
JAVA_OPT="${JAVA_OPT} -Xms50m -Xmx50m -Xmn20m"
JAVA_OPT="${JAVA_OPT} -XX:+UseSerialGC -XX:SurvivorRatio=8"
JAVA_OPT="${JAVA_OPT} -verbose:gc -Xloggc:/Users/xinxingegeya/logs/test_gc_%p.log -XX:+PrintGCDetails -XX:+PrintGCDateStamps"

# $@ 是传给脚本的所有参数的列表
$JAVA ${JAVA_OPT} $@

 

使用 SerialGC 以及参数设置

SerialGC的特点以及使用场景

The serial collector is the default for client style machines in Java SE 5 and 6. With the serial collector, both minor and major garbage collections are done serially (using a single virtual CPU). In addition, it uses a mark-compact collection method. This method moves older memory to the beginning of the heap so that new memory allocations are made into a single continuous chunk of memory at the end of the heap. This compacting of memory makes it faster to allocate new chunks of memory to the heap.

The Serial GC is the garbage collector of choice for most applications that do not have low pause time requirements and run on client-style machines. It takes advantage of only a single virtual processor for garbage collection work (therefore, its name). Still, on today's hardware, the Serial GC can efficiently manage a lot of non-trivial applications with a few hundred MBs of Java heap, with relatively short worst-case pauses (around a couple of seconds for full garbage collections).

Another popular use for the Serial GC is in environments where a high number of JVMs are run on the same machine (in some cases, more JVMs than available processors!). In such environments when a JVM does a garbage collection it is better to use only one processor to minimize the interference on the remaining JVMs, even if the garbage collection might last longer. And the Serial GC fits this trade-off nicely.

Finally, with the proliferation of embedded hardware with minimal memory and few cores, the Serial GC could make a comeback.

指定 -XX:+UseSerialGC 参数,运行程序 打印如下:

➜  bin git:(master) ✗ ./runjavademo.sh com.rocketmq.jvmtest.JvmTestMain01 
Xmx=48.0M
free mem=46.3994140625M
total mem=48.0M
5MB array allocated
Xmx=48.0M
free mem=41.39939880371094M
total mem=48.0M
10MB array allocated
Xmx=48.0M
free mem=32.219390869140625M
total mem=48.0M
OOM!!!
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
        at com.rocketmq.jvmtest.JvmTestMain01.main(JvmTestMain01.java:44)

gc日志如下,

Java HotSpot(TM) 64-Bit Server VM (25.51-b03) for bsd-amd64 JRE (1.8.0_51-b16), built on Jun  8 2015 18:01:11 by "java_re" with gcc 4.2.1 (Based on Apple Inc. build 5658) (LLVM build 2336.11.00)
Memory: 4k page, physical 8388608k(170788k free)

/proc/meminfo:

CommandLine flags: -XX:InitialHeapSize=52428800 -XX:MaxHeapSize=52428800 -XX:MaxNewSize=20971520 -XX:NewSize=20971520 -XX:+PrintGC -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -XX:SurvivorRatio=8 -XX:+UseCompressedClassPointers -XX:+UseCompressedOops -XX:+UseSerialGC 
0.310: [GC (Allocation Failure) 0.310: [DefNew: 6758K->471K(18432K), 0.0104152 secs] 6758K->5591K(49152K), 0.0105287 secs] [Times: user=0.00 sys=0.01, real=0.01 secs] 
0.326: [Full GC (System.gc()) 0.326: [Tenured: 5120K->15828K(30720K), 0.0167847 secs] 16159K->15828K(49152K), [Metaspace: 2802K->2802K(1056768K)], 0.0168987 secs] [Times: user=0.01 sys=0.01, real=0.02 secs] 
0.343: [GC (Allocation Failure) 0.343: [DefNew: 0K->0K(18432K), 0.0017802 secs]0.345: [Tenured: 15828K->15828K(30720K), 0.0027776 secs] 15828K->15828K(49152K), [Metaspace: 2802K->2802K(1056768K)], 0.0046659 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 
0.348: [Full GC (Allocation Failure) 0.348: [Tenured: 15828K->15817K(30720K), 0.0049611 secs] 15828K->15817K(49152K), [Metaspace: 2802K->2802K(1056768K)], 0.0050123 secs] [Times: user=0.00 sys=0.00, real=0.01 secs] 
Heap
 def new generation   total 18432K, used 814K [0x00000007bce00000, 0x00000007be200000, 0x00000007be200000)
  eden space 16384K,   4% used [0x00000007bce00000, 0x00000007bcecbb28, 0x00000007bde00000)
  from space 2048K,   0% used [0x00000007bde00000, 0x00000007bde00000, 0x00000007be000000)
  to   space 2048K,   0% used [0x00000007be000000, 0x00000007be000000, 0x00000007be200000)
 tenured generation   total 30720K, used 15817K [0x00000007be200000, 0x00000007c0000000, 0x00000007c0000000)
   the space 30720K,  51% used [0x00000007be200000, 0x00000007bf172750, 0x00000007bf172800, 0x00000007c0000000)
 Metaspace       used 2833K, capacity 4486K, committed 4864K, reserved 1056768K
  class space    used 306K, capacity 386K, committed 512K, reserved 1048576K

等下篇文章记录一下gc日志的分析过程。

 

使用 Parallel GC 以及参数设置

Parallel GC的特点

The parallel garbage collector uses multiple threads to perform the young genertion garbage collection. By default on a host with N CPUs, the parallel garbage collector uses N garbage collector threads in the collection. The number of garbage collector threads can be controlled with command-line options:

-XX:ParallelGCThreads=<desired number>

On a host with a single CPU the default garbage collector is used even if the parallel garbage collector has been requested. On a host with two CPUs the parallel garbage collector generally performs as well as the default garbage collector and a reduction in the young generationgarbage collector pause times can be expected on hosts with more than two CPUs. The Parallel GC comes in two flavors.

Usage Cases

The Parallel collector is also called a throughput collector. Since it can use multilple CPUs to speed up application throughput. This collector should be used when a lot of work need to be done and long pauses are acceptable. For example, batch processing like printing reports or bills or performing a large number of database queries.

-XX:+UseParallelGC

With this command line option you get a multi-thread young generation collector with a single-threaded old generation collector. The option also does single-threaded compaction of old generation.

Here is a sample command line for starting the Java2Demo:

java -Xmx12m -Xms3m -Xmn1m -XX:PermSize=20m -XX:MaxPermSize=20m -XX:+UseParallelGC -jar c:\javademos\demo\jfc\Java2D\Java2demo.jar
-XX:+UseParallelOldGC

With the -XX:+UseParallelOldGC option, the GC is both a multithreaded young generation collector and multithreaded old generation collector. It is also a multithreaded compacting collector. HotSpot does compaction only in the old generation. Young generation in HotSpot is considered a copy collector; therefore, there is no need for compaction.

Compacting describes the act of moving objects in a way that there are no holes between objects. After a garbage collection sweep, there may be holes left between live objects. Compacting moves objects so that there are no remaining holes. It is possible that a garbage collector be a non-compacting collector. Therefore, the difference between a parallel collector and a parallel compacting collector could be the latter compacts the space after a garbage collection sweep. The former would not.

Here is a sample command line for starting the Java2Demo:

java -Xmx12m -Xms3m -Xmn1m -XX:PermSize=20m -XX:MaxPermSize=20m -XX:+UseParallelOldGC -jar c:\javademos\demo\jfc\Java2D\Java2demo.jar

 

使用 Concurrent Mark Sweep (CMS) Collector 以及参数设置

Concurrent Mark Sweep (CMS) Collector 特点

The Concurrent Mark Sweep (CMS) collector (also referred to as the concurrent low pause collector) collects the tenured generation. It attempts to minimize the pauses due to garbage collection by doing most of the garbage collection work concurrently with the application threads. Normally the concurrent low pause collector does not copy or compact the live objects. A garbage collection is done without moving the live objects. If fragmentation becomes a problem, allocate a larger heap.

Note: CMS collector on young generation uses the same algorithm as that of the parallel collector.

Usage Cases

The CMS collector should be used for applications that require low pause times and can share resources with the garbage collector. Examples include desktop UI application that respond to events, a webserver responding to a request or a database responding to queries.

Command Line Switches

To enable the CMS Collector use:

-XX:+UseConcMarkSweepGC

and to set the number of threads use:

-XX:ParallelCMSThreads=<n>

Here is a sample command line for starting the Java2Demo:

java -Xmx12m -Xms3m -Xmn1m -XX:PermSize=20m -XX:MaxPermSize=20m -XX:+UseConcMarkSweepGC -XX:ParallelCMSThreads=2 -jar c:\javademos\demo\jfc\Java2D\Java2demo.jar

 

使用 G1 Garbage Collector 以及参数设置

G1 Garbage Collector 特点

The Garbage First or G1 garbage collector is available in Java 7 and is designed to be the long term replacement for the CMS collector. The G1 collector is a parallel, concurrent, and incrementally compacting low-pause garbage collector that has quite a different layout from the other garbage collectors described previously. However, detailed discussion is beyond the scope of this OBE.

Command Line Switches

To enable the G1 Collector use:

-XX:+UseG1GC

Here is a sample command line for starting the Java2Demo:

java -Xmx12m -Xms3m -XX:+UseG1GC -jar c:\javademos\demo\jfc\Java2D\Java2demo.jar

==========END==========

转载于:https://my.oschina.net/xinxingegeya/blog/1530211

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值