Java(JVM)内存模型
正如你从上面的图片看到的,JVM内存被分成多个独立的部分。广泛地说,JVM堆内存被分为两部分——年轻代(Young Generation)和老年代(Old Generation)。
年轻代
年轻代是所有新对象产生的地方。当年轻代内存空间被用完时,就会触发垃圾回收。这个垃圾回收叫做Minor GC。年轻代被分为3个部分——Enden区和两个Survivor区。
年轻代空间的要点:
大多数新建的对象都位于Eden区。
当Eden区被对象填满时,就会执行Minor GC。并把所有存活下来的对象转移到其中一个survivor区。
Minor GC同样会检查存活下来的对象,并把它们转移到另一个survivor区。这样在一段时间内,总会有一个空的survivor区。
经过多次GC周期后,仍然存活下来的对象会被转移到年老代内存空间。通常这是在年轻代有资格提升到年老代前通过设定年龄阈值来完成的。
年老代
年老代内存里包含了长期存活的对象和经过多次Minor GC后依然存活下来的对象。通常会在老年代内存被占满时进行垃圾回收。老年代的垃圾收集叫做Major GC。Major GC会花费更多的时间。
Stop the World事件
所有的垃圾收集都是“Stop the World”事件,因为所有的应用线程都会停下来直到操作完成(所以叫“Stop the World”)。
因为年轻代里的对象都是一些临时(short-lived )对象,执行Minor GC非常快,所以应用不会受到(“Stop the World”)影响。
由于Major GC会检查所有存活的对象,因此会花费更长的时间。应该尽量减少Major GC。因为Major GC会在垃圾回收期间让你的应用反应迟钝,所以如果你有一个需要快速响应的应用发生多次Major GC,你会看到超时错误。
垃圾回收时间取决于垃圾回收策略。这就是为什么有必要去监控垃圾收集和对垃圾收集进行调优。从而避免要求快速响应的应用出现超时错误。
永久代
永久代或者“Perm Gen”包含了JVM需要的应用元数据,这些元数据描述了在应用里使用的类和方法。注意,永久代不是Java堆内存的一部分。
永久代存放JVM运行时使用的类。永久代同样包含了Java SE库的类和方法。永久代的对象在full GC时进行垃圾收集。
方法区
方法区是永久代空间的一部分,并用来存储类型信息(运行时常量和静态变量)和方法代码和构造函数代码。
内存池
如果JVM实现支持,JVM内存管理会为创建内存池,用来为不变对象创建对象池。字符串池就是内存池类型的一个很好的例子。内存池可以属于堆或者永久代,这取决于JVM内存管理的实现。
运行时常量池
运行时常量池是每个类常量池的运行时代表。它包含了类的运行时常量和静态方法。运行时常量池是方法区的一部分。
Java栈内存
Java栈内存用于运行线程。它们包含了方法里的临时数据、堆里其它对象引用的特定数据。你可以阅读栈内存和堆内存的区别。
Java 堆内存开关
Java提供了大量的内存开关(参数),我们可以用它来设置内存大小和它们的比例。下面是一些常用的开关:
VM 开关 VM 开关描述
-Xms 设置JVM启动时堆的初始化大小。
-Xmx 设置堆最大值。
-Xmn 设置年轻代的空间大小,剩下的为老年代的空间大小。
-XX:PermGen 设置永久代内存的初始化大小。
-XX:MaxPermGen 设置永久代的最大值。
-XX:SurvivorRatio 提供Eden区和survivor区的空间比例。比如,如果年轻代的大小为10m并且VM开关是-XX:SurvivorRatio=2,那么将会保留5m内存给Eden区和每个Survivor区分配2.5m内存。默认比例是8。
-XX:NewRatio 提供年老代和年轻代的比例大小。默认值是2。
jsat
可以使用jstat命令行工具监控JVM内存和垃圾回收。标准的JDK已经附带了jstat,所以不需要做任何额外的事情就可以得到它。
要运行jstat你需要知道应用的进程id,你可以使用 ps -eaf | grep java 命令获取进程id。
pankaj@Pankaj:~$ ps -eaf | grep Java2Demo.jar
501 9582 11579 0 9:48PM ttys000 0:21.66 /usr/bin/java -Xmx120m -Xms30m -Xmn10m -XX:PermSize=20m -XX:MaxPermSize=20m -XX:+UseG1GC -jar Java2Demo.jar
501 14073 14045 0 9:48PM ttys002 0:00.00 grep Java2Demo.jar
或者
jps -v
pankaj@Pankaj:~$ jstat -gc 9582 1000
S0C S1C S0U S1U EC EU OC OU PC PU YGC YGCT FGC FGCT GCT
1024.0 1024.0 0.0 0.0 8192.0 7933.3 42108.0 23401.3 20480.0 19990.9 157 0.274 40 1.381 1.654
1024.0 1024.0 0.0 0.0 8192.0 8026.5 42108.0 23401.3 20480.0 19990.9 157 0.274 40 1.381 1.654
1024.0 1024.0 0.0 0.0 8192.0 8030.0 42108.0 23401.3 20480.0 19990.9 157 0.274 40 1.381 1.654
1024.0 1024.0 0.0 0.0 8192.0 8122.2 42108.0 23401.3 20480.0 19990.9 157 0.274 40 1.381 1.654
1024.0 1024.0 0.0 0.0 8192.0 8171.2 42108.0 23401.3 20480.0 19990.9 157 0.274 40 1.381 1.654
1024.0 1024.0 48.7 0.0 8192.0 106.7 42108.0 23401.3 20480.0 19990.9 158 0.275 40 1.381 1.656
1024.0 1024.0 48.7 0.0 8192.0 145.8 42108.0 23401.3 20480.0 19990.9 158 0.275 40 1.381 1.656
jstat命令的最后一个参数是每个输出的时间间隔。每隔一秒就会打印出内存和垃圾收集数据。
让我们一起来对每一列的意义进行逐一了解:
S0C和S1C:这一列展示了Survivor0和Survivor1区的当前大小(单位KB)。
S0U和S1U:这一列展示了当前Survivor0和Survivor1区的使用情况(单位KB)。注意:无论任何时候,总会有一个Survivor区是空着的。
EC和EU:这些列展示了Eden区当前空间大小和使用情况(单位KB)。注意:EU的大小一直在增大。而且只要大小接近EC时,就会触发Minor GC并且EU将会减小。
OC和OU:这些列展示了年老代当前空间大小和当前使用情况(单位KB)。
PC和PU:这些列展示了Perm Gen(永久代)当前空间大小和当前使用情况(单位KB)。
YGC和YGCT:YGC这列显示了发生在年轻代的GC事件的数量。YGCT这列显示了在年轻代进行GC操作的累计时间。注意:在EU的值由于minor GC导致下降时,同一行的YGC和YGCT都会增加。
FGC和FGCT:FGC列显示了发生Full GC事件的次数。FGCT显示了进行Full GC操作的累计时间。注意:相对于年轻代的GC使用时间,Full GC所用的时间长很多。
GCT:这一列显示了GC操作的总累计时间。注意:总累计时间是YGCT和FGCT两列所用时间的总和(GCT=YGCT+FGCT)。
jstat的优点,我们同样可以在没有GUI的远程服务器上运行jstat。
Java VisualVM及Visual GC插件
如果你想在GUI里查看内存和GC,那么可以使用jvisualvm工具。Java VisualVM同样是JDK的一部分,所以你不需要单独去下载。
在终端运行jvisualvm命令启动Java VisualVM程序。一旦启动程序,你需要从Tools->Plugins选项安装Visual GC插件,就像下面图片展示的。
安装完Visual GC插件后,从左边栏打开应用并把视角转到Visual GC部分。你将会得到关于JVM内存和垃圾收集详情,如下图所示。
远程使用VisualVM
-Dcom.sun.management.jmxremote.port=8888 -Dcom.sun.management.jmxremote.ssl=false -Dcom.sun.management.jmxremote.authenticate=false -Djava.rmi.server.hostname=192.168.154.149
echo $JAVA_HOME
实战
初始 -Xms1024m -Xmx1024m -XX:MaxPermSize=256m
初始内存占用
S0C 42m
S1C 42m
EC 256m
OC 682m
PC 34m
年轻代大约
42+42+256=340m
老年代大约682m
加起来堆1024m
所以堆大小=年轻代+年老代
年老代和年轻代默认比例是2:1
JMeter数据
Number of Threads(users):线程数目,使用线程模拟的用户的数目。
Ramp-Up Period:上升周期,在多长的时间内创建所有的线程数目。
Loop Count:循环次数,如果需要一直重复发送请求、勾选复选框Forever。
5个并发下数据
吞吐量 1242/分钟
评价响应时间 234ms
gc取样数据
S0C S1C S0U S1U EC EU OC OU PC PU YGC YGCT FGC FGCT GCT
43648.0 43648.0 2937.1 0.0 262208.0 173271.5 699072.0 1568.5 31424.0 31402.4 4 0.043 1 0.044 0.088
43648.0 43648.0 2937.1 0.0 262208.0 173271.5 699072.0 1568.5 31424.0 31402.8 4 0.043 1 0.044 0.088
43648.0 43648.0 2937.1 0.0 262208.0 173271.5 699072.0 1568.5 31424.0 31402.8 4 0.043 1 0.044 0.088
43648.0 43648.0 2937.1 0.0 262208.0 173271.5 699072.0 1568.5 31424.0 31402.8 4 0.043 1 0.044 0.088
43648.0 43648.0 2937.1 0.0 262208.0 173271.5 699072.0 1568.5 31424.0 31403.5 4 0.043 1 0.044 0.088
43648.0 43648.0 2937.1 0.0 262208.0 173271.5 699072.0 1568.5 31424.0 31403.5 4 0.043 1 0.044 0.088
43648.0 43648.0 2937.1 0.0 262208.0 173271.5 699072.0 1568.5 31424.0 31403.5 4 0.043 1 0.044 0.088
43648.0 43648.0 2937.1 0.0 262208.0 173271.5 699072.0 1568.5 31424.0 31403.5 4 0.043 1 0.044 0.088
43648.0 43648.0 2937.1 0.0 262208.0 194281.7 699072.0 1568.5 33920.0 33787.7 4 0.043 1 0.044 0.088
43648.0 43648.0 2937.1 6692.4 262208.0 0.0 699072.0 1568.5 37568.0 37524.8 5 0.066 1 0.044 0.110
43648.0 43648.0 0.0 9190.0 262208.0 81498.7 699072.0 1568.5 42944.0 42940.7 5 0.066 1 0.044 0.110
43648.0 43648.0 0.0 9190.0 262208.0 98784.1 699072.0 1568.5 43136.0 42982.4 5 0.066 1 0.044 0.110
43648.0 43648.0 0.0 9190.0 262208.0 116412.5 699072.0 1568.5 43136.0 43014.6 5 0.066 1 0.044 0.110
43648.0 43648.0 0.0 9190.0 262208.0 134419.8 699072.0 1568.5 43136.0 43041.4 5 0.066 1 0.044 0.110
43648.0 43648.0 0.0 9190.0 262208.0 161130.7 699072.0 1568.5 43136.0 43071.8 5 0.066 1 0.044 0.110
43648.0 43648.0 0.0 9190.0 262208.0 179128.9 699072.0 1568.5 43136.0 43086.9 5 0.066 1 0.044 0.110
43648.0 43648.0 0.0 9190.0 262208.0 194697.5 699072.0 1568.5 43136.0 43097.4 5 0.066 1 0.044 0.110
43648.0 43648.0 0.0 9190.0 262208.0 215756.0 699072.0 1568.5 43136.0 43113.6 5 0.066 1 0.044 0.110
43648.0 43648.0 0.0 9190.0 262208.0 233960.2 699072.0 1568.5 43136.0 43121.1 5 0.066 1 0.044 0.110
43648.0 43648.0 0.0 9190.0 262208.0 249564.5 699072.0 1568.5 43136.0 43135.1 5 0.066 1 0.044 0.110
43648.0 10816.0 10459.7 0.0 295040.0 23018.1 699072.0 1568.5 43328.0 43144.0 6 0.088 1 0.044 0.132
43648.0 10816.0 10459.7 0.0 295040.0 43884.6 699072.0 1568.5 43328.0 43206.8 6 0.088 1 0.044 0.132
43648.0 10816.0 10459.7 0.0 295040.0 55718.0 699072.0 1568.5 43328.0 43217.4 6 0.088 1 0.044 0.132
43648.0 10816.0 10459.7 0.0 295040.0 63191.0 699072.0 1568.5 43328.0 43221.7 6 0.088 1 0.044 0.132
43648.0 10816.0 10459.7 0.0 295040.0 99057.7 699072.0 1568.5 43328.0 43236.0 6 0.088 1 0.044 0.132
43648.0 10816.0 10459.7 0.0 295040.0 115182.8 699072.0 1568.5 43328.0 43242.1 6 0.088 1 0.044 0.132
43648.0 10816.0 10459.7 0.0 295040.0 129365.3 699072.0 1568.5 43328.0 43248.8 6 0.088 1 0.044 0.132
43648.0 10816.0 10459.7 0.0 295040.0 151771.1 699072.0 1568.5 43328.0 43256.3 6 0.088 1 0.044 0.132
43648.0 10816.0 10459.7 0.0 295040.0 166619.5 699072.0 1568.5 43328.0 43265.0 6 0.088 1 0.044 0.132
43648.0 10816.0 10459.7 0.0 295040.0 183726.4 699072.0 1568.5 43328.0 43273.6 6 0.088 1 0.044 0.132
43648.0 10816.0 10459.7 0.0 295040.0 205264.4 699072.0 1568.5 43328.0 43280.3 6 0.088 1 0.044 0.132
43648.0 10816.0 10459.7 0.0 295040.0 230258.2 699072.0 1568.5 43328.0 43288.0 6 0.088 1 0.044 0.132
43648.0 10816.0 10459.7 0.0 295040.0 247175.5 699072.0 1568.5 43328.0 43293.8 6 0.088 1 0.044 0.132
43648.0 10816.0 10459.7 0.0 295040.0 259764.8 699072.0 1568.5 43328.0 43296.3 6 0.088 1 0.044 0.132
43648.0 10816.0 10459.7 0.0 295040.0 277736.7 699072.0 1568.5 43328.0 43312.2 6 0.088 1 0.044 0.132
每隔20秒 young gc 一次 时间大约0.216 ms
9856.0 640.0 0.0 329280.0 117749.1 699072.0 16172.4 43520.0 43513.7 20 0.270 1 0.044 0.314
10368.0 9856.0 640.0 0.0 329280.0 126884.7 699072.0 16172.4 43520.0 43513.7 20 0.270 1 0.044 0.314
10368.0 9856.0 640.0 0.0 329280.0 135822.9 699072.0 16172.4 43520.0 43513.7 20 0.270 1 0.044 0.314
10368.0 9856.0 640.0 0.0 329280.0 176039.3 699072.0 16172.4 43520.0 43518.8 20 0.270 1 0.044 0.314
10368.0 9856.0 640.0 0.0 329280.0 217231.0 699072.0 16172.4 43712.0 43520.3 20 0.270 1 0.044 0.314
10368.0 9856.0 640.0 0.0 329280.0 262311.1 699072.0 16172.4 43712.0 43520.7 20 0.270 1 0.044 0.314
10368.0 9856.0 640.0 0.0 329280.0 306637.9 699072.0 16172.4 43712.0 43521.7 20 0.270 1 0.044 0.314
9536.0 9856.0 0.0 3416.2 329280.0 29272.8 699072.0 16716.4 43712.0 43522.5 21 0.283 1 0.044 0.327
9536.0 9856.0 0.0 3416.2 329280.0 73940.1 699072.0 16716.4 43712.0 43522.7 21 0.283 1 0.044 0.327
9536.0 9856.0 0.0 3416.2 329280.0 115594.2 699072.0 16716.4 43712.0 43528.4 21 0.283 1 0.044 0.327
9536.0 9856.0 0.0 3416.2 329280.0 155286.5 699072.0 16716.4 43712.0 43528.4 21 0.283 1 0.044 0.327
9536.0 9856.0 0.0 3416.2 329280.0 196495.2 699072.0 16716.4 43712.0 43529.0 21 0.283 1 0.044 0.327
9536.0 9856.0 0.0 3416.2 329280.0 241023.6 699072.0 16716.4 43712.0 43529.2 21 0.283 1 0.044 0.327
9536.0 9856.0 0.0 3416.2 329280.0 285944.3 699072.0 16716.4 43712.0 43530.4 21 0.283 1 0.044 0.327
9536.0 9856.0 0.0 3416.2 329280.0 326643.2 699072.0 16716.4 43712.0 43533.6 21 0.283 1 0.044 0.327
9536.0 9024.0 2832.2 0.0 330944.0 38738.8 699072.0 17889.0 43712.0 43535.6 22 0.290 1 0.044 0.334
9536.0 9024.0 2832.2 0.0 330944.0 83569.4 699072.0 17889.0 43712.0 43535.6 22 0.290 1 0.044 0.334
9536.0 9024.0 2832.2 0.0 330944.0 127286.3 699072.0 17889.0 43712.0 43535.6 22 0.290 1 0.044 0.334
9536.0 9024.0 2832.2 0.0 330944.0 169335.3 699072.0 17889.0 43712.0 43535.7 22 0.290 1 0.044 0.334
9536.0 9024.0 2832.2 0.0 330944.0 210436.3 699072.0 17889.0 43712.0 43536.7 22 0.290 1 0.044 0.334
9536.0 9024.0 2832.2 0.0 330944.0 238269.2 699072.0 17889.0 43712.0 43537.2 22 0.290 1 0.044 0.334
9536.0 9024.0 2832.2 0.0 330944.0 286474.5 699072.0 17889.0 43712.0 43539.6 22 0.290 1 0.044 0.334
9536.0 9024.0 2832.2 0.0
大约每隔12秒触发一次young gc 没有触发full gc
调整为30线程
压测结论
由于是自己开发机器 设置的线程数在多也只能最大达到8个并发所以发现调整线程数是无意义的
压测还是需要专门的压测机
这个只是一个实验 以备自己忘记
堆内存年轻代随着压力增大打满的越来越快
cpu
线程数
调整策略
线程数改为8个在相同条件下改变参数
大约每20秒一次gc
改变参数为
-Xmx2048m -Xms2048m -XX:NewRatio=2 -XX:SurvivorRatio=4 -XX:MaxTenuringThreshold=10 -XX:+UseConcMarkSweepGC -XX:CMSFullGCsBeforeCompaction=5 -XX:+UseCMSCompactAtFullCollection -XX:MaxPermSize=256m
启动后内存
s0 s1 : 113m
eden : 455m
SurvivorRatio比例正确
old : 1365m
NewRatio比例正确
每隔24秒gc一次
gc时间间隔拉长 吞吐量没有提升
改变参数调大eden 和 年轻代
-Xmx2048m -Xms2048m -XX:NewRatio=1 -XX:SurvivorRatio=6 -XX:MaxTenuringThreshold=10 -XX:+UseConcMarkSweepGC -XX:CMSFullGCsBeforeCompaction=5 -XX:+UseCMSCompactAtFullCollection -XX:MaxPermSize=256m
s0 s1 : 128m
eden: 768m
old: 1024m
jstat 发现gc的时间间隔拉长 gc时间变短
S0C S1C S0U S1U EC EU OC OU PC PU YGC YGCT FGC FGCT GCT
116480.0 116480.0 5969.8 0.0 466048.0 263945.3 1398144.0 1586.4 37952.0 37878.2 2 0.055 1 0.076 0.132
116480.0 116480.0 5969.8 0.0 466048.0 301035.7 1398144.0 1586.4 37952.0 37900.7 2 0.055 1 0.076 0.132
116480.0 116480.0 5969.8 0.0 466048.0 332603.0 1398144.0 1586.4 38144.0 37932.8 2 0.055 1 0.076 0.132
116480.0 116480.0 5969.8 0.0 466048.0 369815.8 1398144.0 1586.4 38144.0 37977.6 2 0.055 1 0.076 0.132
116480.0 116480.0 5969.8 0.0 466048.0 409383.9 1398144.0 1586.4 38144.0 38002.2 2 0.055 1 0.076 0.132
116480.0 116480.0 5969.8 0.0 466048.0 453217.9 1398144.0 1586.4 38144.0 38025.0 2 0.055 1 0.076 0.132
116480.0 116480.0 0.0 13224.4 466048.0 61354.8 1398144.0 1586.4 38144.0 38050.6 3 0.105 1 0.076 0.181
116480.0 116480.0 0.0 13224.4 466048.0 106414.5 1398144.0 1586.4 38336.0 38111.3 3 0.105 1 0.076 0.181
116480.0 116480.0 0.0 13224.4 466048.0 138232.7 1398144.0 1586.4 38336.0 38118.3 3 0.105 1 0.076 0.181
116480.0 116480.0 0.0 13224.4 466048.0 188380.2 1398144.0 1586.4 38336.0 38157.8 3 0.105 1 0.076 0.181
116480.0 116480.0 0.0 13224.4 466048.0 232302.2 1398144.0 1586.4 38336.0 38170.5 3 0.105 1 0.076 0.181
116480.0 116480.0 0.0 13224.4 466048.0 282167.2 1398144.0 1586.4 38336.0 38190.8 3 0.105 1 0.076 0.181
116480.0 116480.0 0.0 13224.4 466048.0 322206.3 1398144.0 1586.4 38336.0 38203.5 3 0.105 1 0.076 0.181
116480.0 116480.0 0.0 13224.4 466048.0 361496.7 1398144.0 1586.4 38336.0 38212.0 3 0.105 1 0.076 0.181
116480.0 116480.0 0.0 13224.4 466048.0 400863.7 1398144.0 1586.4 38336.0 38215.9 3 0.105 1 0.076 0.181
116480.0 116480.0 0.0 13224.4 466048.0 443993.4 1398144.0 1586.4 38336.0 38223.6 3 0.105 1 0.076 0.181
116480.0 116480.0 15983.7 0.0 466048.0 38096.7 1398144.0 1586.4 38336.0 38245.9 4 0.143 1 0.076 0.220
116480.0 116480.0 15983.7 0.0 466048.0 84894.5 1398144.0 1586.4 38336.0 38255.4 4 0.143 1 0.076 0.220
116480.0 116480.0 15983.7 0.0 466048.0 125473.0 1398144.0 1586.4 38336.0 38261.2 4 0.143 1 0.076 0.220
116480.0 116480.0 15983.7 0.0 466048.0 172343.2 1398144.0 1586.4 38336.0 38269.3 4 0.143 1 0.076 0.220
116480.0 116480.0 15983.7 0.0 466048.0 216860.1 1398144.0 1586.4 38336.0 38287.2 4 0.143 1 0.076 0.220
116480.0 116480.0 15983.7 0.0 466048.0 260240.4 1398144.0 1586.4 38528.0 38295.0 4 0.143 1 0.076 0.220
116480.0 116480.0 15983.7 0.0 466048.0 305636.0 1398144.0 1586.4 38528.0 38302.1 4 0.143 1 0.076 0.220