内存溢出不可怕,手足无措才尴尬
内存溢出错误简称OOM,也就是 Out Of Memory Error , 是Java中常见也是最严重的错误之一. C及 C++程序最烦人的内存泄漏和溢出错误,在Java程序中由于垃圾回收似乎已经不存在了,其实不然,它一直都在。
前一阵子,产品线就出现了一个内存溢出的问题,结合实例,总结回顾一下此类问题的原因和分析方法。
1. 原因
先来看看 Java 所使用的内存空间,Java虚拟机将内存分为如下5个区域:
# | 内存区域 | 线程私有 | 说明 |
---|---|---|---|
1 | Method Area - 方法区 | 否 | 也称为永久区,保存类的元数据,包括类型信息,常量池,域变量信息,方法信息等 |
2 | Heap - 堆内存 | 否 | 存放 Java对象实例的内存池,由垃圾收集回收,通常按新生代和老年代进行分代收集 |
3 | JVM Language Stacks - Java 语言栈 | 是 | 栈的基本数据结构是栈帧Stack Frame, 存放了方法的局部变量表,操作数栈,动态连接方法和返回地址等 |
4 | PC Registers - Program Counter Registers 程序计数寄存器 | 是 | 处理器内部的寄存器,记录正在执行的Java字节码地址 |
5 | Native Method Stacks - 本地方法栈 | 是 | 用于其他语言实现的本地方法 |
如下图所示
JVM Spec我们在写程序时,如果用到了递归,要注意避免调用层次过深,否则会引起 StackOverFlowError,也可用-Xss参数来调整栈空间大小。而更为常见的 OutOfMemory 内存溢出错误,一般来说有如下常见的原因:
- JVM 的本地内存(native memory)耗尽
- Java 堆内存耗尽
- 永久代(java7)或元空间(Java8以上) 内存耗尽
- JVM 花费了太长时间进行垃圾收集(超过98%的时间用于GC或在整个GC期间,只有不到2%的堆被回收)
2. 实例
让我们写几个实际的例子来演示这个内存溢出错误,并分析其原因和分析的方法
- 例一:分配超大数组造成 OOM
执行./run_oom_demo.sh heap 10000000
// java.lang.OutOfMemoryError:Java heap space
public void noHeapSpace() {
Integer[] array = new Integer[this.loopCount];
}
- 例二:创建过多类造成 OOM
执行./run_oom_demo.sh meta 10000000
//java.lang.OutOfMemoryError: Metaspace or PermSpace
public void noMetaSpace() throws CannotCompileException {
for (int i = 0; i < this.loopCount; i++) {
Class c = classPool.makeClass("com.github.walterfan.hellometrics.OomDemo" + i).toClass();
log.info("{}. makeClass {}", i, c.getName());
}
}
- 例三:分配过多线程造成 OOM
执行./run_oom_demo.sh native 10000000
// java.lang.OutOfMemoryError: unable to create new native thread
public void noNativeMemory() {
for (int i = 0; i < this.loopCount; ++i) {
new Thread() {
public void run() {
try {
Thread.sleep(1000000);
} catch(InterruptedException e) { }
}
}.start();
log.info("Thread " + i + " created");
}
}
- 例四:错误使用 Multimap 造成OOM
这个例子稍微复杂一些,本来是想要统计全球有多少种常用语言,使用这些语言是哪些国家和地区。
因为语言和国家是有限的,所以用 map 来存储,并且也没有在使用过后进行清除。一开始,使用Map<String, Set<String>> langCountriesMap = new HashMap<>()
来存储,因为 Set 不会保存重复的记录,所以无论运行多少次,都不会造成内存溢出。
后来,为了简化代码,将 Map<String, Set<String>> 换成 Multimap<String, String>,没有考虑到 Guava 库的这个数据结构是value 不是想象中的 Set<String> ,而是一个 List<String> ,这样内存会随着调用次数的增加不断增长。
代码如下:
private Multimap<String, String> localeMultiMap = ArrayListMultimap.create();
private Map<String, Set<String>> langCountriesMap = new HashMap<>();
// java.lang.OutOfMemoryError: Java heap space
private void noHeapDemo() {
for(long i =0; i < loopCount; ++i) {
for(Locale locale: Locale.getAvailableLocales()) {
this.addLocale(locale.getLanguage(), locale.getCountry());
log.debug("{}/{}. {}", i, totalCount, locale);
}
}
wait4Input(totalCount + " added, exit?");
printLocales();
}
public void addLocale(String key, String value) {
if(Strings.isBlank(key) || Strings.isBlank(value)) {
return;
}
totalCount++;
log.debug("addLocale {} -> {}", key, value);
if("multimap".equals(demoType)) {
this.localeMultiMap.put(key, value);
} else {
Set<String> countries = langCountriesMap.get(key);
if(null == countries) {
countries = new HashSet<>();
langCountriesMap.put(key, countries);
}
countries.add(value);
}
}
1)先用Map<String, Set<String>> 来存储,执行命令 ./run_oom_demo.sh hashmap 10000000
, 一切正常,有如下输出。
java -server -Xms128m -Xmx256m -XX:MaxMetaspaceSize=64m -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=./heapdump_2020-01-27_12_52_02.hprof -verbosegc -XX:+UseParallelGC -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -XX:+PrintHeapAtGC -XX:+PrintGCDateStamps -Xloggc:./gc.log -XX:StringTableSize=100003 -Dsun.net.inetaddr.ttl=15 -Djava.security.egd=file:/dev/./urandom -Duser.timezone=GMT -Dfile.encoding=UTF8 -Dcom.sun.management.jmxremote=true -Dcom.sun.management.jmxremote.port=8091 -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.authenticate=true -Dcom.sun.management.jmxremote.password.file=./jmxremote.password -Dcom.sun.management.jmxremote.access.file=./jmxremote.access -cp ./target/hellometrics-1.0-SNAPSHOT-jar-with-dependencies.jar com.github.walterfan.hellometrics.OomDemo -t hashmap -c 10000000
178 [main] INFO c.g.walterfan.hellometrics.OomDemo - --- run demo hashmap ---
1140000000 added, exit?
81054 [main] INFO c.g.walterfan.hellometrics.OomDemo - 1. language: ar, countries: EG,AE,JO,SY,BH,IQ,YE,KW,LY,SA,QA,SD,MA,DZ,LB,TN,OM
81055 [main] INFO c.g.walterfan.hellometrics.OomDemo - 2. language: be, countries: BY
81055 [main] INFO c.g.walterfan.hellometrics.OomDemo - 3. language: bg, countries: BG
81055 [main] INFO c.g.walterfan.hellometrics.OomDemo - 4. language: ca, countries: ES
81055 [main] INFO c.g.walterfan.hellometrics.OomDemo - 5. language: cs, countries: CZ
81055 [main] INFO c.g.walterfan.hellometrics.OomDemo - 6. language: da, countries: DK
81055 [main] INFO c.g.walterfan.hellometrics.OomDemo - 7. language: de, countries: DE,AT,CH,LU,GR
81055 [main] INFO c.g.walterfan.hellometrics.OomDemo - 8. language: el, countries: CY,GR
81056 [main] INFO c.g.walterfan.hellometrics.OomDemo - 9. language: en, countries: SG,AU,IN,MT,ZA,PH,GB,NZ,IE,US,CA
81056 [main] INFO c.g.walterfan.hellometrics.OomDemo - 10. language: es, countries: PR,SV,UY,HN,PY,CL,MX,DO,CO,BO,GT,ES,VE,CR,PA,AR,CU,PE,NI,EC,US
81056 [main] INFO c.g.walterfan.hellometrics.OomDemo - 11. language: et, countries: EE
81056 [main] INFO c.g.walterfan.hellometrics.OomDemo - 12. language: fi, countries: FI
81056 [main] INFO c.g.walterfan.hellometrics.OomDemo - 13. language: fr, countries: BE,CH,LU,FR,CA
81056 [main] INFO c.g.walterfan.hellometrics.OomDemo - 14. language: ga, countries: IE
81056 [main] INFO c.g.walterfan.hellometrics.OomDemo - 15. language: hi, countries: IN
81056 [main] INFO c.g.walterfan.hellometrics.OomDemo - 16. language: hr, countries: HR
81056 [main] INFO c.g.walterfan.hellometrics.OomDemo - 17. language: hu, countries: HU
81057 [main] INFO c.g.walterfan.hellometrics.OomDemo - 18. language: in, countries: ID
81057 [main] INFO c.g.walterfan.hellometrics.OomDemo - 19. language: is, countries: IS
81057 [main] INFO c.g.walterfan.hellometrics.OomDemo - 20. language: it, countries: CH,IT
81057 [main] INFO c.g.walterfan.hellometrics.OomDemo - 21. language: iw, countries: IL
81057 [main] INFO c.g.walterfan.hellometrics.OomDemo - 22. language: ja, countries: JP
81057 [main] INFO c.g.walterfan.hellometrics.OomDemo - 23. language: ko, countries: KR
81058 [main] INFO c.g.walterfan.hellometrics.OomDemo - 24. language: lt, countries: LT
81058 [main] INFO c.g.walterfan.hellometrics.OomDemo - 25. language: lv, countries: LV
81058 [main] INFO c.g.walterfan.hellometrics.OomDemo - 26. language: mk, countries: MK
81058 [main] INFO c.g.walterfan.hellometrics.OomDemo - 27. language: ms, countries: MY
81058 [main] INFO c.g.walterfan.hellometrics.OomDemo - 28. language: mt, countries: MT
81059 [main] INFO c.g.walterfan.hellometrics.OomDemo - 29. language: nl, countries: BE,NL
81059 [main] INFO c.g.walterfan.hellometrics.OomDemo - 30. language: no, countries: NO
81059 [main] INFO c.g.walterfan.hellometrics.OomDemo - 31. language: pl, countries: PL
81059 [main] INFO c.g.walterfan.hellometrics.OomDemo - 32. language: pt, countries: BR,PT
81059 [main] INFO c.g.walterfan.hellometrics.OomDemo - 33. language: ro, countries: RO
81059 [main] INFO c.g.walterfan.hellometrics.OomDemo - 34. language: ru, countries: RU
81059 [main] INFO c.g.walterfan.hellometrics.OomDemo - 35. language: sk, countries: SK
81060 [main] INFO c.g.walterfan.hellometrics.OomDemo - 36. language: sl, countries: SI
81060 [main] INFO c.g.walterfan.hellometrics.OomDemo - 37. language: sq, countries: AL
81060 [main] INFO c.g.walterfan.hellometrics.OomDemo - 38. language: sr, countries: CS,RS,ME,BA
81060 [main] INFO c.g.walterfan.hellometrics.OomDemo - 39. language: sv, countries: SE
81060 [main] INFO c.g.walterfan.hellometrics.OomDemo - 40. language: th, countries: TH
81060 [main] INFO c.g.walterfan.hellometrics.OomDemo - 41. language: tr, countries: TR
81061 [main] INFO c.g.walterfan.hellometrics.OomDemo - 42. language: uk, countries: UA
81061 [main] INFO c.g.walterfan.hellometrics.OomDemo - 43. language: vi, countries: VN
81061 [main] INFO c.g.walterfan.hellometrics.OomDemo - 44. language: zh, countries: TW,HK,SG,CN
Used memory: 42m
2)然后再改用 Multimap, 执行命令 ./run_oom_demo.sh multimap 10000000
$ ./run_oom_demo.sh multimap 10000000
java -server -Xms128m -Xmx256m -XX:MaxMetaspaceSize=64m -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=./heapdump_2020-01-27_13_02_08.hprof -verbosegc -XX:+UseParallelGC -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -XX:+PrintHeapAtGC -XX:+PrintGCDateStamps -Xloggc:./gc.log -XX:StringTableSize=100003 -Dsun.net.inetaddr.ttl=15 -Djava.security.egd=file:/dev/./urandom -Duser.timezone=GMT -Dfile.encoding=UTF8 -Dcom.sun.management.jmxremote=true -Dcom.sun.management.jmxremote.port=8091 -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.authenticate=true -Dcom.sun.management.jmxremote.password.file=./jmxremote.password -Dcom.sun.management.jmxremote.access.file=./jmxremote.access -cp ./target/hellometrics-1.0-SNAPSHOT-jar-with-dependencies.jar com.github.walterfan.hellometrics.OomDemo -t multimap -c 10000000
156 [main] INFO c.g.walterfan.hellometrics.OomDemo - --- run demo multimap ---
java.lang.OutOfMemoryError: Java heap space
Dumping heap to ./heapdump_2020-01-27_13_02_08.hprof ...
Heap dump file created [424123288 bytes in 0.779 secs]
Exception in thread "main" java.lang.OutOfMemoryError: Java heap space
at java.util.Arrays.copyOf(Arrays.java:3181)
at java.util.ArrayList.grow(ArrayList.java:265)
at java.util.ArrayList.ensureExplicitCapacity(ArrayList.java:239)
at java.util.ArrayList.ensureCapacityInternal(ArrayList.java:231)
at java.util.ArrayList.add(ArrayList.java:462)
at com.google.common.collect.AbstractMapBasedMultimap.put(AbstractMapBasedMultimap.java:202)
at com.google.common.collect.AbstractListMultimap.put(AbstractListMultimap.java:100)
at com.google.common.collect.ArrayListMultimap.put(ArrayListMultimap.java:66)
at com.github.walterfan.hellometrics.OomDemo.addLocale(OomDemo.java:48)
at com.github.walterfan.hellometrics.OomDemo.noHeapDemo(OomDemo.java:114)
at com.github.walterfan.hellometrics.OomDemo.run(OomDemo.java:103)
at com.github.walterfan.hellometrics.OomDemo.launchTool(OomDemo.java:159)
at com.github.walterfan.hellometrics.OomDemo.main(OomDemo.java:190)
发生了内存溢出,第一时间就要察看上述的日志输出,找出导致内存溢出的地方,有时情况没有这么简单,内存泄漏存在多处并且是缓慢累积而成的。这时,我们要分析堆转储文件
用三种方法可以生成堆转储文件:
- 1)使用jmap -dump选项在运行时获取堆转储比如
jmap -dump:format=b,file=/tmp/heap.hprof $pid
来导出 heap dump file。 - 2)使用 jconsole 选项通过 HotSpotDiagnosticMXBean 获取堆转储。
- 通过指定-XX:+ HeapDumpOnOutOfMemoryError VM选项引发OutOfMemoryError时,将生成堆转储;
这里我们用 -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=./heapdump.hprof
这两个启动选项让JVM 在内存溢出时生成堆转储文件
3. 分析
JDK 自带的 jhat 和 jvisualvm 都可以对 heap dump file 进行分析,最给力的工具当属 eclipse 出品的 内存分析工具 MAT(Memory Analyzer Tool)
1) jvisualvm
以 jvisualvm 为例, 执行命令 jvisualvm
, 在 File 菜单中选取 Load 来打开堆转储文件
可以看到这个堆转储文件的大体情况:
heap dump summary内存溢出异常的线程调用栈:
thread call stack而最有问题的是 Multimap中的值是一个 List<String> 存放的是国家名,占用绝大部分的内存:
heap dump classes2) jhat
jhat 是 JDK 自带的命令,它可以解析Java堆转储文件并启动一个Web服务器。 其默认侦听端口是7000, 可以通过 --port 参数改成其他端口。 jhat支持预先设计的查询(例如“显示已知类“ Foo”的所有实例”)以及OQL(对象查询语言)(一种类似于SQL的查询语言,用于查询堆转储)
执行命令 jhat -J-mx1512m -port 2020 heapdump_2020-01-27_13_02_08.hprof
用浏览器打开 http://localhost:2020, 内容与上面的 jvisualvm 所产生的内容差不多, 在此略过。
打开 http://localhost:2020/oqlhelp/ 可以获取 OQL 的帮助
3) mat
MAT(Memory Analyzer Tool)是 Eclipse 著名的内存分析工具,它是一种快速且功能丰富的Java堆分析器,可用来查找内存泄漏并减少内存消耗,它可以用来分析包含数亿个对象的堆转储文件,快速计算对象的保留大小,查看谁阻止垃圾收集器进行垃圾回收,产生报告以自动报告可疑的内存泄漏。
它的内存泄漏报告尤其有用:
例如本例中的Multimap的内存问题就可以快速的诊断出来:
4.实例的完整源代码
- 类 OomDemo.java
package com.github.walterfan.hellometrics;
import com.google.common.collect.ArrayListMultimap;
import com.google.common.collect.Multimap;
import javassist.CannotCompileException;
import javassist.ClassPool;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.cli.*;
import org.apache.commons.lang3.math.NumberUtils;
import org.apache.logging.log4j.util.Strings;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.*;
import java.util.concurrent.atomic.AtomicInteger;
import java.util.stream.Collectors;
/**
* @Author: Walter Fan
* @Date: 22/1/2020, Wed
**/
@Slf4j
public class OomDemo {
private static ClassPool classPool = ClassPool.getDefault();
private int totalCount = 0;
//key: language, value: countries
private Multimap<String, String> localeMultiMap = ArrayListMultimap.create();
private Map<String, Set<String>> langCountriesMap = new HashMap<>();
private final String demoType;
private final int loopCount;
public OomDemo(String demoType, int loopCount) {
this.demoType = demoType;
this.loopCount = loopCount;
}
public void addLocale(String key, String value) {
if(Strings.isBlank(key) || Strings.isBlank(value)) {
return;
}
totalCount++;
log.debug("addLocale {} -> {}", key, value);
if("multimap".equals(demoType)) {
this.localeMultiMap.put(key, value);
} else {
Set<String> countries = langCountriesMap.get(key);
if(null == countries) {
countries = new HashSet<>();
langCountriesMap.put(key, countries);
}
countries.add(value);
}
}
// java.lang.OutOfMemoryError:Java heap space
public void noHeapSpace() {
Integer[] array = new Integer[this.loopCount];
}
//java.lang.OutOfMemoryError: Metaspace or PermSpace
public void noMetaSpace() throws CannotCompileException {
for (int i = 0; i < this.loopCount; i++) {
Class c = classPool.makeClass("com.github.walterfan.hellometrics.OomDemo" + i).toClass();
log.info("{}. makeClass {}", i, c.getName());
}
}
// java.lang.OutOfMemoryError: unable to create new native thread
public void noNativeMemory() {
for (int i = 0; i < this.loopCount; ++i) {
new Thread() {
public void run() {
try {
Thread.sleep(1000000);
} catch(InterruptedException e) { }
}
}.start();
log.info("Thread " + i + " created");
}
}
public void run() {
log.info("--- run demo {} ---", this.demoType);
try {
switch (this.demoType) {
case "heap":
noHeapSpace();
break;
case "native":
noNativeMemory();
break;
case "meta":
noMetaSpace();
break;
default:
noHeapDemo();
}
} catch(Exception e) {
log.error("run error of " + this.demoType + ", " + this.loopCount, e);
}
}
// java.lang.OutOfMemoryError: Java heap space
private void noHeapDemo() {
for(long i =0; i < loopCount; ++i) {
for(Locale locale: Locale.getAvailableLocales()) {
this.addLocale(locale.getLanguage(), locale.getCountry());
log.debug("{}/{}. {}", i, totalCount, locale);
}
}
wait4Input(totalCount + " added, exit?");
printLocales();
}
public static String wait4Input(String prompt) {
System.out.print(prompt);
System.out.flush();
try (InputStreamReader is = new InputStreamReader(System.in)) {
BufferedReader in = new BufferedReader(is);
return in.readLine();
} catch (IOException e) {
System.err.println(e.getMessage());
}
return "";
}
public void printLocales() {
final AtomicInteger i = new AtomicInteger(0);
if("multimap".equals(demoType)) {
localeMultiMap.keySet().stream().sorted().forEach(key -> {
log.info("{}. language: {}, countries: {} ", i.incrementAndGet(),
key,
localeMultiMap.get(key).stream().collect(Collectors.joining(",")));
});
} else {
langCountriesMap.keySet().stream().sorted().forEach(key -> {
log.info("{}. language: {}, countries: {} ", i.incrementAndGet(),
key,
langCountriesMap.get(key).stream().collect(Collectors.joining(",")));
});
}
}
public static void launchTool(String type, String count) {
int loopCount = NumberUtils.toInt(count, 1);
OomDemo demo = new OomDemo(type, loopCount);
demo.run();
}
public static void main(String[] args) {
Options options = new Options();
Option opt = new Option("t", "type", true, "optional, sets the collection type: " +
"heap|native|meta|multimap|hashmap");
options.addOption(opt);
opt = new Option("c", "count", true, "optional, forever or loop number");
options.addOption(opt);
HelpFormatter hf = new HelpFormatter();
hf.setWidth(110);
CommandLine commandLine = null;
CommandLineParser parser = new DefaultParser();
try {
commandLine = parser.parse(options, args);
if (commandLine.hasOption('h')) {
hf.printHelp("helper", options, true);
}
launchTool(commandLine.getOptionValue("t"), commandLine.getOptionValue("c"));
} catch (Exception e) {
log.error("launch error: ", e);
hf.printHelp("helper", options, true);
}
}
}
- pom.xml
<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/maven-v4_0_0.xsd">
<modelVersion>4.0.0</modelVersion>
<groupId>com.github.walterfan</groupId>
<artifactId>hellometrics</artifactId>
<packaging>jar</packaging>
<version>1.0-SNAPSHOT</version>
<name>hellometrics</name>
<url>http://maven.apache.org</url>
<properties>
<java.version>1.8</java.version>
<dropwizard-metrics.version>3.1.0</dropwizard-metrics.version>
<jackson.version>2.6.3</jackson.version>
<guava.version>18.0</guava.version>
</properties>
<dependencies>
<dependency>
<groupId>junit</groupId>
<artifactId>junit</artifactId>
<version>4.12</version>
<scope>test</scope>
</dependency>
<dependency>
<groupId>io.dropwizard.metrics</groupId>
<artifactId>metrics-httpclient</artifactId>
<version>${dropwizard-metrics.version}</version>
</dependency>
<dependency>
<groupId>org.projectlombok</groupId>
<artifactId>lombok</artifactId>
<version>1.16.18</version>
<scope>provided</scope>
</dependency>
<dependency>
<groupId>com.google.guava</groupId>
<artifactId>guava</artifactId>
<version>${guava.version}</version>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.6</version>
</dependency>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
<version>2.2.2.RELEASE</version>
</dependency>
<dependency>
<groupId>commons-cli</groupId>
<artifactId>commons-cli</artifactId>
<version>1.4</version>
</dependency>
<dependency>
<groupId>org.apache.commons</groupId>
<artifactId>commons-lang3</artifactId>
<version>3.9</version>
</dependency>
<dependency>
<groupId>javassist</groupId>
<artifactId>javassist</artifactId>
<version>3.12.1.GA</version>
</dependency>
</dependencies>
<build>
<plugins>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.8</source>
<target>1.8</target>
</configuration>
</plugin>
<plugin>
<artifactId>maven-assembly-plugin</artifactId>
<configuration>
<archive>
<manifest>
<mainClass>com.github.walterfan.hellometrics.OomDemo</mainClass>
</manifest>
</archive>
<descriptorRefs>
<descriptorRef>jar-with-dependencies</descriptorRef>
</descriptorRefs>
</configuration>
<executions>
<execution>
<id>make-assembly</id> <!-- this is used for inheritance merges -->
<phase>package</phase> <!-- bind to the packaging phase -->
<goals>
<goal>single</goal>
</goals>
</execution>
</executions>
</plugin>
</plugins>
</build>
</project>
- 运行脚本 run_oom_demo.sh
HOME_PATH=.
CLASS_PATH=./target/hellometrics-1.0-SNAPSHOT-jar-with-dependencies.jar
MAIN_CLASS=com.github.walterfan.hellometrics.OomDemo
startTime=$(date +%Y-%m-%d_%H_%M_%S)
HEAP_OPTS="-Xms128m -Xmx256m -XX:MaxMetaspaceSize=64m -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=$HOME_PATH/heapdump_$startTime.hprof"
GC_OPTS="-verbosegc -XX:+UseParallelGC -XX:+PrintGCDetails -XX:+PrintGCTimeStamps -XX:+PrintHeapAtGC -XX:+PrintGCDateStamps -Xloggc:./gc.log"
JAVA_OPTS="-server $HEAP_OPTS $GC_OPTS -XX:StringTableSize=100003 -Dsun.net.inetaddr.ttl=15 -Djava.security.egd=file:/dev/./urandom -Duser.timezone=GMT -Dfile.encoding=UTF8"
JMX_OPS="-Dcom.sun.management.jmxremote=true -Dcom.sun.management.jmxremote.port=8091 -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.authenticate=true -Dcom.sun.management.jmxremote.password.file=./jmxremote.password -Dcom.sun.management.jmxremote.access.file=./jmxremote.access"
CMD_TYPE=multimap
CMD_COUNT=100000000
if [ $# -eq 1 ]
then
CMD_TYPE=$1
fi
if [ $# -eq 2 ]
then
CMD_TYPE=$1
CMD_COUNT=$2
fi
APP_OPTS="-t $CMD_TYPE -c $CMD_COUNT"
cmd="java $JAVA_OPTS $JMX_OPS -cp $CLASS_PATH $MAIN_CLASS $APP_OPTS"
echo $cmd
$cmd
代码链接:https://github.com/walterfan/helloworld/tree/master/hellometrics