hello云胜

技术与生活

0%

关于容器内JVM的实验

默认的,jvm的初始内存Xms为服务器内存的1/64,最大内存Xmx为内存的1/4

实验验证下docker中jvm的内存使用情况

代码

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
@SpringBootApplication
public class OomApplication {

public static void main(String[] args) {
System.out.println("===============");
SpringApplication.run(OomApplication.class, args);
System.out.println("********************");
oom();
}

private static void oom() {
Runtime rt = Runtime.getRuntime();
//返回java虚拟机中的初始内存总量Xms,默认应该是机器内存的1/64
long totalMemory = rt.totalMemory();
//返回java虚拟机可以使用的最大内存量Xms,默认应该是机器的1/4
long maxMemory = rt.maxMemory();
System.out.println("Total_Memory(-Xms ) = " + totalMemory + " 字节 " + (totalMemory / (double) 1024 / 1024) + "MB");
System.out.println("Max_Memory(-Xmx ) = " + maxMemory + " 字节 " + (maxMemory / (double) 1024 / 1024) + "MB");

List l = new ArrayList<>();
while (true) {
byte b[] = new byte[1048576];
l.add(b);
System.out.println("使用的内存:"+ rt.totalMemory() / (double) 1024 / 1024 + "M,free memory: " + rt.freeMemory() / (double) 1024 / 1024);
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}

}

限制docker容器的内存

Dockerfile

1
2
3
4
5
FROM openjdk:8u191-jdk-alpine3.9
COPY ./oom-1.0.0.jar /
RUN apk add --no-cache tini
ENTRYPOINT ["tini"]
CMD ["java", "-jar", "oom-1.0.0.jar"]
1
docker run -d -m 1000m --memory-swap 1000m --name myjdk  myjdk:1.0.0

-m 限制容器可用内存为1000m

–memory-swap是容器可以使用的物理内存和可以使用的 swap 之和,设置的和memory一样大,就是不允许使用swap

设置为0,或者不设置,表示swap为memory的2倍

-1,它表示容器程序使用内存的受限,而可以使用的 swap 空间使用不受限制(宿主机有多少 swap 容器就可以使用多少)。

打印的日志

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
34
35
36
37
38
39
40
41
Total_Memory(-Xms ) =  16252928 字节  15.5MB
Max_Memory(-Xmx ) = 253427712 字节 241.6875MB
使用的内存:15.5M,free memory: 8.396034240722656
使用的内存:15.5M,free memory: 7.396018981933594
使用的内存:15.5M,free memory: 6.396003723144531
使用的内存:15.5M,free memory: 5.395988464355469
使用的内存:15.5M,free memory: 4.454139709472656
使用的内存:15.5M,free memory: 3.4541244506835938
使用的内存:15.5M,free memory: 2.4541091918945312
使用的内存:15.5M,free memory: 1.4540939331054688
使用的内存:31.47265625M,free memory: 17.306068420410156
使用的内存:31.47265625M,free memory: 16.306053161621094
...
使用的内存:31.47265625M,free memory: 2.3054122924804688
使用的内存:67.7265625M,free memory: 37.36358642578125
使用的内存:67.7265625M,free memory: 36.36357116699219
...
使用的内存:67.7265625M,free memory: 3.3696060180664062
使用的内存:149.89453125M,free memory: 84.09593200683594
使用的内存:149.89453125M,free memory: 83.09591674804688
...
使用的内存:149.89453125M,free memory: 8.10455322265625
使用的内存:149.89453125M,free memory: 7.1045379638671875
使用的内存:241.6875M,free memory: 98.41573333740234
使用的内存:241.6875M,free memory: 98.41573333740234
...
使用的内存:241.6875M,free memory: 0.5089797973632812
Exception in thread "main" java.lang.reflect.InvocationTargetException
at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method)
at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62)
at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43)
at java.lang.reflect.Method.invoke(Method.java:498)
at org.springframework.boot.loader.MainMethodRunner.run(MainMethodRunner.java:49)
at org.springframework.boot.loader.Launcher.launch(Launcher.java:107)
at org.springframework.boot.loader.Launcher.launch(Launcher.java:58)
at org.springframework.boot.loader.JarLauncher.main(JarLauncher.java:88)
Caused by: java.lang.OutOfMemoryError: Java heap space
at com.yunsheng.demo.OomApplication.oom(OomApplication.java:30)
at com.yunsheng.demo.OomApplication.main(OomApplication.java:16)
... 8 more

看到初始Xms确实为1G内存的1/64,Xmx为1G内存的1/4

然后内存耗尽之后,申请的基本上是当前内存的一倍还多一点。

验证jdk命令

进入容器,实现jps,jstat等jdk命令可以使用

jmap进行堆dump也是可以的

image-20210928144320898

验证异常退出dump

Dockerfile

1
2
3
4
5
6
7
8
FROM openjdk:8u191-jdk-alpine3.9
COPY ./oom-1.0.0.jar /
COPY ./start.sh /
WORKDIR /
RUN apk add --no-cache tini
ENTRYPOINT ["tini"]
#CMD ["java", "-jar", "oom-1.0.0.jar"]
CMD sh start.sh

在程序jvm的启动参数中增加异常退出时进行堆转储

1
nohup java -XX:+HeapDumpOnOutOfMemoryError -XX:HeapDumpPath=/my-heap-dump.hprof -jar oom-1.0.0.jar > log.log 2>&1 &

image-20210928164531723

验证ok

测试s2i方式打镜像启动

同样的代码

同样的容器启动命令

发现s2i方式启动的java进行,其内存的设置是依赖的物理机内存