JVM工具备注(一)

【参考资料】
【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 list = new ArrayList();
	public static int _1M = 1024*1024;

	public static void main(String[] args) {

		while (true){
			try {
				byte[] content = new byte[_1M];
				list.add(content);
				System.out.println(list.size());
				System.out.println("totalMemory : " + Runtime.getRuntime().totalMemory()/_1M);
				System.out.println("freeMemory  : " + Runtime.getRuntime().freeMemory()/_1M);

				Thread.sleep(500);
			} catch (InterruptedException e) {
				e.printStackTrace();
			}
		}
	}
}
 
  

启动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
  1. 当内存分配超过10M时,即年轻代没有足够的空间,则触发了一次full GC,此时一部分内存被移到老生代
  2. 当程序继续执行超过20M占用时,程序报错java.lang.OutOfMemoryError: Java heap space
  3. 注意Metaspace,元数据空间,存储class定义等,以前也叫持久代
  4. 如果我们不将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
垃圾回收策略总结
  1. 整个堆空间,分为新生代和老生代,其中新生代又分eden区和两个Survivor区(from 和 to )
  2. 对象优先在eden区分配
  3. 当eden区没有足够的空间,则触发一次minor GC,这类GC非常频繁,回收速度也很快
  4. 大对象直接进入老年代,根据参数PretenureSizeThreashold定义
  5. JVM对每个对象定义一个年龄技术器,当经历过minor GC,被从eden区移动到supervisor,则年龄为1;此后每经历一次minor GC就加1
  6. 当年龄增加到某个值以上,比如15,则移入到老年代
  7. 当发生minor GC,如果需要移入老生代的数据空间大于老生代剩余空间,或者不符合担保阈值(一种内存预留策略),则仍然触发Full GC;
jps
  1. 类似linux下的ps,查看所有的Java虚拟机进程
  2. 参数-q,只输出虚拟机的进程ID
24532
24933
24934
  1. 参数-m,输出进程启动时传递给main函数的参数
24934 App hello fredric
  1. 参数-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
  1. 参数-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
jstat
  1. 用于监视本地或远程虚拟机进程中的类加载、内存、垃圾收集、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 所有垃圾回收时间
  1. jstat在远程监控时,需要被监控主机提供rmi支持,远程方法调用(Remote Method Invocation),通常是通过在主机侧利用jstatd命令来启动一个rmi server。

你可能感兴趣的:(java)