綠 青 色

GC(Garbage Collection)

GC(Garbage Collection)

GC背景

​  创建对象会消耗内存,如果不回收对象占用的内存,内存使用率会越来越高,最终出现OutOfMemoryError(OOM)
​  在C++中专门有一个"析构函数"来回收对象占用的内存,Java有一个专门的GC线程,定时执行清理对象占用的内存

​  从JDK1.3开始到现在:GC经历了4个阶段的变化

​​    1、串行垃圾收集

​​    2、并行垃圾收集

​​    3、并发垃圾收集

​​    4、G1垃圾收集(Garbage First)

内存分配

JVM执行程序,将内存分为5块:

​  程序计数器:记录当前程序里面的指令执行的状态。

​  JVM栈:每个方法一旦调用,就会将该方法入栈,每个方法都有自己的局部变量列表,局部方法列表存储了对象的引用。

​  ​ 注意:一旦方法不停的入栈,占满了栈内存的空间就会出现StackOverflowError错误。

​  本地方法栈:Java由C++ 演变而来,建立在C++基础上的,C++提供了很多dll(动态链接库)给Java调用,主要加载C++的DLL,和我们程序没有多大关联。

​  堆栈:所有new产生的对象都在堆中,GC主要就是回收堆栈内存对象占用的内存空间。

​  方法区:当一个类成功加载到JVM,JVM就会存储该类的Class信息(package、类型信息class、属性信息field、方法信息method、构造方法信息、静态属性和方法信息)。

堆内存配置

​  -Xmx 最大堆内存 默认值:整个计算机物理内存的1/4 4G 最大值64G
​ 建议不要超过计算机物理内存的1/2

​  -Xms 初始堆内存 默认值:整个计算机物理内存的1/64 256M
注意:工作中上面两个参数的配置最好一致(可以减少垃圾收集的频率)

​  -Xmn 设置堆内存年轻代大小 整个堆内存3/8

​  -Xss 占内存每个线程的大小 默认1M 128k

​  -XX:+PrintGCDetails 打印GC信息

以上JVM参数在哪里配置???

​  1. 可以在Eclipse启动之前配置 Eclipse.ini(软件启动项的根目录)

​  ​  -XX:+UseG1GC 使用G1方式进行垃圾收集

​  ​  XX:+UseStringDeduplication主要是用来消除长时间存活的重复字符串对象 ,注意它只能用在G1垃圾收集

​  2. Eclipse配置JDK的时候设置

​  串行
​  ​  -Xmx4096m -Xms4096m -Xmn1536m -XX:+PrintGCDetails

​  并行
​​  ​  -Xmx4096m -Xms4096m -Xmn1536m -XX:+UseParallelGC -XX:+UseParallelOldGC -XX:ParallelGCThreads=2 -XX:+PrintGCDetails
​  ​  设置垃圾收集为并行收集,通常用于服务器端,场景:多个客户端连接一个服务器,此时服务器会采用并行垃圾收集。

​  并发
​  ​  -XX:+UseConcMarkSweepGC 并发垃圾收集
​  ​  -Xmx4096m -Xms4096m -Xmn1536m -XX:+UseConcMarkSweepGC -XX:+PrintGCDetails

​  G1
​  ​  -XX:+UseG1GC 使用G1作为垃圾收集
​​  ​  XX:G1HeapRegionSize=16m 设置每个区块大小
​  ​  -Xmx4096m -Xms4096m -XX:+UseG1GC -XX:G1HeapRegionSize=16m -XX:+PrintGCDetails

​  将堆内存划分为不连续分配的空间 ,将你的堆内存划分为1个或者多个区块(Region),每个区块分配的内存大小在(1m、2m、4m、8m、16m、32m)之间

	@Test
	public void testStringBuffer() {
		for(;;) {
			byte[] by = new byte[1*1024*1024];
		}
	}
	
	@Test
	public void testString() {
		String str="";
		for(int i=0;i<500000;i++) {
			str+="i";
		}
	}
	
	/**
	 * -Xmx16m -Xms16m -Xmn6m -XX:+PrintGCDetails
	 * 会出现OutOfMemoryError:因为垃圾收集的频率赶不上创建对象的频率
	 * 随便编写一个程序,如何让他永远不死(OutOfMemoryError,StackOverflowError),随便编写一个程序让他立马死掉
	 * javac命令编译程序  java命令运行程序  在bin目录下
	 * 你平时在工作中除了使用上面两个命令,还使用过哪些命令?
	 * javap 反编译字节码
	 * jconsole 监控程序
	 * jvisualvm 监控程序
	 * javadoc命令
	 */
	@Test
	public void testByte() {
		for(;;) {
			//每次循环分配10MB的内存
			byte[] by =new byte[1024*1024*1024];
		}
	}

​  ​  小结:eden(伊甸区永远都是存储最新鲜的对象,也就是刚刚new出的对象),一旦伊甸区的使用率到达一个阀值(85%),启动GC,回收年轻代的对象将伊甸区不活动的对象转移到幸存区,当幸存区到达阀值,再次做垃圾回收,如果回收失败,将对象放入老年代,如果老年代到达阀值,会做full gc(全量回收),如果回收失败OOM(OutOfMemory)错误.

​  G1垃圾收集

​  ​  [GC (Allocation Failure) [PSYoungGen: 1179648K->1270K(1376256K)] 1179648K->1278K(3997696K), 0.0011735 secs][Times: user=0.00 sys=0.00, real=0.00 secs]

​  GC启动垃圾收集

​  ​  Allocation Failure: 分配空间失败
​  ​  PSYoungGen: GC回收年轻代的内存

​  ​  1179648K->1270K(1376256K)
​  ​  1376256K 年轻代分配的内存空间
​  ​  1179648K 垃圾收集之前年轻代使用的空间
​  ​  ​ 年轻代内存使用率86% 将进行垃圾收集(minor 最轻量级的垃圾收集)
​  ​  1270K 垃圾收集之后年轻代使用的空间

​  ​  1179648K->1278K(3997696K)
​  ​  3997696K:表示整个堆内存(年轻代+老年代)的总空间
​  ​  1179648K:表示整个堆内存(年轻代+老年代)的在垃圾收集之前的使用空间
​  ​  1278K:表示整个堆内存(年轻代+老年代)的在垃圾收集之后的使用空间

Heap
//年轻代总空间 1571328K ,使用空间837686K 
 PSYoungGen      total 1571328K, used 837686K [0x0000000760000000, 0x00000007c0000000, 0x00000007c0000000)
//表示 eden space年轻代的伊甸区使用空间 1569792K ,使用率837686/1569792=53%                                     
  eden space 1569792K, 53% used [0x0000000760000000,0x0000000793143430,0x00000007bfd00000)
 //from space表示 年轻代的幸存1区分配了1536k,使用率52%                               
  from space 1536K, 52% used [0x00000007bfd00000,0x00000007bfdca510,0x00000007bfe80000)
// to   space 表示 年轻代的幸存2区分配了1536k,使用率0%                             
  to   space 1536K, 0% used [0x00000007bfe80000,0x00000007bfe80000,0x00000007c0000000)
//ParOldGen       total老年代分配的空间2621440K  使用了952K                           
 ParOldGen       total 2621440K, used 952K [0x00000006c0000000, 0x0000000760000000, 0x0000000760000000)
  object space 2621440K, 0% used [0x00000006c0000000,0x00000006c00ee0a0,0x0000000760000000)
 Metaspace       used 4511K, capacity 4990K, committed 5248K, reserved 1056768K
  class space    used 532K, capacity 562K, committed 640K, reserved 1048576K
//Full GC 表示全量垃圾收集[年轻代和老年代的内存]
// 40369/40960=98% 老年代使用率到达98% 危险:老年代如果回收失败就会出现OutOfMemoryError
[Full GC (Ergonomics) [PSYoungGen: 404K->0K(24064K)] [ParOldGen: 40369K->1397K(40960K)] 40774K->1397K(65024K), [Metaspace: 4497K->4497K(1056768K)], 0.0029315 secs] [Times: user=0.00 sys=0.00, real=0.00 secs] 

​  3. 在你编写程序的启动类上设置

posted @ 2019-09-16 22:45  LYANG-A  阅读(857)  评论(0编辑  收藏  举报