【参考资料】
【1】《深入理解Java虚拟机》
【2】https://www.cnblogs.com/aspirant/p/7001082.html
【2】https://blog.csdn.net/ft305977550/article/details/78517372
public class App {
public static List
启动JVM参数为: -verbose:gc -Xms20M -Xmx20M -Xmn10M -XX:+PrintGCDetails -XX:SurvivorRatio=8
Xms是指启动时可以分配的内存大小;Xmx是运行是最大占用的内存大小;Xmn表示年轻代为10M;执行结果:
1
totalMemory : 19
freeMemory : 15
2
totalMemory : 19
freeMemory : 14
3
totalMemory : 19
freeMemory : 13
Heap
PSYoungGen total 9216K, used 5657K [0x00000007bf600000, 0x00000007c0000000, 0x00000007c0000000)
eden space 8192K, 69% used [0x00000007bf600000,0x00000007bfb866b8,0x00000007bfe00000)
from space 1024K, 0% used [0x00000007bff00000,0x00000007bff00000,0x00000007c0000000)
to space 1024K, 0% used [0x00000007bfe00000,0x00000007bfe00000,0x00000007bff00000)
ParOldGen total 10240K, used 0K [0x00000007bec00000, 0x00000007bf600000, 0x00000007bf600000)
object space 10240K, 0% used [0x00000007bec00000,0x00000007bec00000,0x00000007bf600000)
Metaspace used 3217K, capacity 4500K, committed 4864K, reserved 1056768K
class space used 352K, capacity 388K, committed 512K, reserved 1048576K
上面的执行结果表示:
1.年轻代的eden区在程序启动时占用了大约2~3M 内存(不知道为什么)?
2.新分配的对象占用eden区,每次增加1M
totalMemory : 19
freeMemory : 11
[GC (Allocation Failure) [PSYoungGen: 7377K->706K(9216K)] 7377K->5834K(19456K), 0.0040136 secs] [Times: user=0.01 sys=0.01, real=0.01 secs]
[Full GC (Ergonomics) [PSYoungGen: 706K->0K(9216K)] [ParOldGen: 5128K->5742K(10240K)] 5834K->5742K(19456K), [Metaspace: 3211K->3211K(1056768K)], 0.0055605 secs] [Times: user=0.01 sys=0.00, real=0.00 secs]
6
totalMemory : 19
freeMemory : 12
7
totalMemory : 19
freeMemory : 11
8
totalMemory : 19
freeMemory : 10
9
totalMemory : 19
freeMemory : 9
10
totalMemory : 19
freeMemory : 8
Heap
PSYoungGen total 9216K, used 5685K [0x00000007bf600000, 0x00000007c0000000, 0x00000007c0000000)
eden space 8192K, 69% used [0x00000007bf600000,0x00000007bfb8d790,0x00000007bfe00000)
from space 1024K, 0% used [0x00000007bfe00000,0x00000007bfe00000,0x00000007bff00000)
to space 1024K, 0% used [0x00000007bff00000,0x00000007bff00000,0x00000007c0000000)
ParOldGen total 10240K, used 5742K [0x00000007bec00000, 0x00000007bf600000, 0x00000007bf600000)
object space 10240K, 56% used [0x00000007bec00000,0x00000007bf19bb58,0x00000007bf600000)
Metaspace used 3221K, capacity 4500K, committed 4864K, reserved 1056768K
class space used 352K, capacity 388K, committed 512K, reserved 1048576K
- 当内存分配超过10M时,即年轻代没有足够的空间,则触发了一次full GC,此时一部分内存被移到老生代
- 当程序继续执行超过20M占用时,程序报错java.lang.OutOfMemoryError: Java heap space
- 注意Metaspace,元数据空间,存储class定义等,以前也叫持久代
- 如果我们不将byte数组插入static的list,则会触发minor GC,即在新生代中执行的垃圾回收,如下:
totalMemory : 19
freeMemory : 13
Heap
PSYoungGen total 9216K, used 6292K [0x00000007bf600000, 0x00000007c0000000, 0x00000007c0000000)
eden space 8192K, 68% used [0x00000007bf600000,0x00000007bfb79338,0x00000007bfe00000)
from space 1024K, 67% used [0x00000007bff00000,0x00000007bffac010,0x00000007c0000000)
to space 1024K, 0% used [0x00000007bfe00000,0x00000007bfe00000,0x00000007bff00000)
ParOldGen total 10240K, used 16K [0x00000007bec00000, 0x00000007bf600000, 0x00000007bf600000)
object space 10240K, 0% used [0x00000007bec00000,0x00000007bec04000,0x00000007bf600000)
Metaspace used 3221K, capacity 4500K, committed 4864K, reserved 1056768K
class space used 352K, capacity 388K, committed 512K, reserved 1048576K
- 整个堆空间,分为新生代和老生代,其中新生代又分eden区和两个Survivor区(from 和 to )
- 对象优先在eden区分配
- 当eden区没有足够的空间,则触发一次minor GC,这类GC非常频繁,回收速度也很快
- 大对象直接进入老年代,根据参数PretenureSizeThreashold定义
- JVM对每个对象定义一个年龄技术器,当经历过minor GC,被从eden区移动到supervisor,则年龄为1;此后每经历一次minor GC就加1
- 当年龄增加到某个值以上,比如15,则移入到老年代
- 当发生minor GC,如果需要移入老生代的数据空间大于老生代剩余空间,或者不符合担保阈值(一种内存预留策略),则仍然触发Full GC;
- 类似linux下的ps,查看所有的Java虚拟机进程
- 参数-q,只输出虚拟机的进程ID
24532
24933
24934
- 参数-m,输出进程启动时传递给main函数的参数
24934 App hello fredric
- 参数-l,输出主类的全名,或启动的jar包
24949 sun.tools.jps.Jps
24933 org.jetbrains.jps.cmdline.Launcher
24934 com.fredric.demo.jvm.App
24871 org.jetbrains.idea.maven.server.RemoteMavenServer
- 参数-v,输出虚拟机启动时的JVM参数
24934 App -javaagent:/Applications/IntelliJ IDEA.app/Contents/lib/idea_rt.jar=54798:/Applications/IntelliJ IDEA.app/Contents/bin -Dfile.encoding=UTF-8
24871 RemoteMavenServer -Djava.awt.headless=true -Didea.version==2017.3.6 -Xmx768m -Didea.maven.embedder.version=3.3.9 -Dfile.encoding=UTF-8
- 用于监视本地或远程虚拟机进程中的类加载、内存、垃圾收集、JIT编译器等情况;例如:
fredricdeMacBook-Pro:~ fredric$ jstat -gc 24934 250 2
S0C S1C S0U S1U EC EU OC OU MC MU CCSC CCSU YGC YGCT FGC FGCT GCT
5120.0 5120.0 0.0 0.0 33280.0 3330.6 87552.0 0.0 4480.0 770.0 384.0 75.8 0 0.000 0 0.000 0.000
5120.0 5120.0 0.0 0.0 33280.0 3330.6 87552.0 0.0 4480.0 770.0 384.0 75.8 0 0.000 0 0.000 0.000
1.1 -gc 代表监控java堆的状况
1.2 24934 代表监控对象的虚拟机ID
1.3 250 代表监控间隔250ms
1.4 2 代表监控次数为2次
字段符号 | 含义 |
---|---|
S0C | Survivor区(from) 容量大小 |
S1C | Survivor区(to) 容量大小 |
S0U | Survivor区(from) 已使用大小 |
S1U | Survivor区(to) 已使用大小 |
EC | Eden区容量大小 |
EU | Eden区使用大小 |
OC | 老生代容量大小 |
OU | 老生代使用大小 |
MC | 元数据空间容量大小 |
MU | 元数据空间使用大小 |
CCSC | 当前压缩类容量大小,对于64位平台,为了压缩JVM对象中的_klass指针的大小,引入了类指针压缩空间 |
CCSU | 当前压缩类使用大小 |
YGC | 年轻代垃圾回收次数 |
YGCT | 年轻代垃圾回收时间 |
FGC | full GC垃圾回收次数 |
FGCT | full GC垃圾回收时间 |
GCT | 所有垃圾回收时间 |
- jstat在远程监控时,需要被监控主机提供rmi支持,远程方法调用(Remote Method Invocation),通常是通过在主机侧利用jstatd命令来启动一个rmi server。