java中的gc log解读

gc log是java程序在出现内存问题时候最好的查看问题的有利日志。下面我们来一步一步分析gc log。

首先,默认java程序是不会开启gc log,我们可以在给jvm参数加上-XX:+PrintGCDetails (这个只是我们在本地调试使用,在生成环境下不可使用。

下面我们可以模拟一个程序,来查看日志。

public class GcLog {
	static final int MB = 1024 * 1024;
	static void printGC() {

		byte[] b1, b2, b3, b4;
		b1 = new byte[MB];
		b2 = new byte[MB];
		b3 = new byte[MB];
		b4 = new byte[2*MB];
	}
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		printGC();
	}
}

可以给可以jvm加上如下的启动参数:-Xmx10M -Xms10M -Xmn6M -XX:+PrintGCDetails -XX:SurvivorRatio=7

从代码,可以看到jvm分配的内存大小一共为10M,其中老变态4M,年轻态6M,同时针对年轻态eden和Survivor共享6M,分配的比例为7:1:1,其中eden大小为4.6M,Survivor的两个区域各自为0.6M

这里我们默认采用CMS垃圾回收,下面我们运行程序,会看到如下的日志

[GC [DefNew: 3298K->149K(5504K), 0.0053498 secs] 3298K->3221K(9600K), 0.0053750 secs] [Times: user=0.00 sys=0.00, real=0.01 secs]
Heap
 def new generation   total 5504K, used 2391K [0x33e60000, 0x34460000, 0x34460000)
  eden space 4864K,  46% used [0x33e60000, 0x34090b28, 0x34320000)
  from space 640K,  23% used [0x343c0000, 0x343e5418, 0x34460000)
  to   space 640K,   0% used [0x34320000, 0x34320000, 0x343c0000)
 tenured generation   total 4096K, used 3072K [0x34460000, 0x34860000, 0x34860000)
   the space 4096K,  75% used [0x34460000, 0x34760030, 0x34760200, 0x34860000)
 compacting perm gen  total 12288K, used 376K [0x34860000, 0x35460000, 0x38860000)
   the space 12288K,   3% used [0x34860000, 0x348be298, 0x348be400, 0x35460000)
    ro space 10240K,  55% used [0x38860000, 0x38de3320, 0x38de3400, 0x39260000)
    rw space 12288K,  55% used [0x39260000, 0x39906128, 0x39906200, 0x39e60000)

下面来从程序的角度分析日志的。

程序中按照顺序申请了1M-->1M--->1M--->2M的内存

当第一次申请1M的时候,新生态空间足够直接放入

当第二次申请1M的时候,新生态空间依然足够,直接放入

当第三次申请1M的时候,新生态空间依然足够,直接放入

当第四次申请1M的时候,新生态空间不足开始GC,而此时有3个1M的对象,而Survivor区域不满1M,所以直接进入老年态,这是原来的3个1M对象进入老年态,2M的对象进入eden

[GC [DefNew: 3298K->149K(5504K), 0.0053498 secs] 3298K->3221K(9600K), 0.0053750 secs] [Times: user=0.00 sys=0.00, real=0.01 secs] 

看一下这行:

DefNew表示新生态:3298K->149K(5504K), 0.0053498 secs

表示新生态由3298K回收变成了149K,即之前的3M回收了,5504K表示该区域的总内存大小

3298K->3221K(9600K), 0.0053750 secs] 表示整个jvm堆的大小由于没有可以回收的对象,所以总大小本质没发生改变,9600K是java的总堆大小9600K。(虽然分配10M,其中还有持久态等其他内存区域)

[Times: user=0.00 sys=0.00, real=0.01 secs] 表示gc所花费的系统资源

-------------------------------------------------------------------------------华丽分割线---------------------------------------------------------------------------------------------------------

再来看看这堆详细的信息

Heap
 def new generation   total 5504K, used 2391K [0x33e60000, 0x34460000, 0x34460000)------------->新生态的大小,total,used
  eden space 4864K,  46% used [0x33e60000, 0x34090b28, 0x34320000)
  from space 640K,  23% used [0x343c0000, 0x343e5418, 0x34460000)------------->本例中由于该区域很小,无法放入对象,所以其实没使用到。
  to   space 640K,   0% used [0x34320000, 0x34320000, 0x343c0000)
 tenured generation   total 4096K, used 3072K [0x34460000, 0x34860000, 0x34860000)------------->老年态
   the space 4096K,  75% used [0x34460000, 0x34760030, 0x34760200, 0x34860000)
 compacting perm gen  total 12288K, used 376K [0x34860000, 0x35460000, 0x38860000)------------->由于老年态共4M,已经放入3M了,所以开启了压缩。
   the space 12288K,   3% used [0x34860000, 0x348be298, 0x348be400, 0x35460000)
    ro space 10240K,  55% used [0x38860000, 0x38de3320, 0x38de3400, 0x39260000)
    rw space 12288K,  55% used [0x39260000, 0x39906128, 0x39906200, 0x39e60000)

对于生成环境下的java程序可以加上来生成gc log,方便出现问题的时候去排查

-verbose:gc -Xloggc:/usr/gclog -XX:+PrintGCDetails XX:+PrintGCTimeStamps

暂时先到这边,jvm内存模型这里就不多说了,后续我会写一些jvm优化已经在线调试线上系统的工具。

时间: 2024-10-15 19:09:52

java中的gc log解读的相关文章

java 中的gc问题

前几天服务器出现了一些问题,然后组内同学就这些问题写过一篇文章,下面是顺着那篇文章,接着写一些内容. 一:GC算法的类型 GC也就是垃圾回收,和我们日常中的垃圾回收一样,语言中的垃圾回收也是表示对已经不再使用的对象进行清理,获得更多的内存空间:日常生活中也是一样的,比如去餐厅吃饭,每个人都要用到碗筷进行回收,一直都用之前的话,肯定是会用完的,那这个碗筷回收的算法时怎么样的呢?对于餐厅来说最好的方式是,在每个人吃完之后,自己将碗筷放到垃圾回收的地方,但是这样有两个问题,一个是餐厅就餐人的素质要比较

Java中System.gc()和Runtime.getRuntime().gc()

(1) GC是垃圾收集的意思(Gabage Collection),内存处理是编程人员容易出现问题的地方,忘记或者错误的内存回收会导致程序或系统的不稳定甚至崩溃,Java提供的GC功能可以自动监测对象是否超过作用域从而达到自动回收内存的目的,Java语言没有提供释放已分配内存的显示操作方法. (2) 对于GC来说,当程序员创建对象时,GC就开始监控这个对象的地址.大小以及使用情况.通常,GC采用有向图的方式记录和管理堆(heap)中的所有对象.通过这种方式确定哪些对象是"可达的",哪些

图解Java中的GC(分代收集器)

前面在Java垃圾收集算法中讲过垃圾收集算法中的分代收集器,今天看了一个视频发现里面将的也很不错,所以决定再总结一下. 我们知道,在分代收集算法中堆空间被分为新生代和老年代.因为新生代中对象的存活率比较低,所以一般采用复制算法,老年代的存活率一般比较高,一般使用"标记-清理"或者"标记-整理"算法进行回收. 上面的这个图已经很清楚的将堆的分区展现出来了. 下面我们来看看具体的算法过程. 新创建的对象一般放在新生代的Enden区,如下图所示. 上面对象中,绿色代表的是

java中的GC(gabage collection)如何工作

1. “引用记数(reference counting)”是一种简单但速度很慢的垃圾回收技术.每个对象都含有一个引用记数器,当有引用连接至对象时,引用计数加1.当引用离开作用域或被置 为null时,引用计数减1.虽然管理引用记数的开销不大,但需要在整个程序生命周期中持续地开销.垃圾回收器会在含有全部对象的列表上遍历,当发现某个 对象的引用计数为0时,就释放其占用的空间.这种方法有个缺陷,如果对象之间存在循环引用,可能会出现“对象应该被回收,但引用计数却不为零”的情况.对 垃圾回收器而言,定位这样

关于Java中线程池的解读

之前的面试中多次被问到线程池的相关内容,所以在之后的时间内我仔细的学习了一下线程池的相关内容. 1.使用线程池的意义 复用:类似WEB服务器等系统,长期来看内部需要使用大量的线程处理请求,而单次请求响应时间通常比较短,此时Java基于操作系统的本地调用方式大量的创建和销毁线程本身会成为系统的一个性能瓶颈和资源浪费.若使用线程池技术可以实现工作线程的复用,即一个工作线程创建和销毁的生命周期期间内可以执行处理多个任务,从而总体上降低线程创建和销毁的频率和时间,提升了系统性能. 流控:服务器资源有限,

C++、Java、JavaScript中的日志(log)

编程思想之日志记录 什么是log? 相信你一定用日记写过点滴心事,或是用空间.微信.微博刷着动态,记录你每天的喜怒哀乐!在程序中也有一种类似的东西,记录着他主人(应用程序)每天的行踪,他叫日志(log).日记--是人类生活的记事本,日志(log)--是程序运行状况的记事本. 顾名思义,日志(log,后面均以log称之)就是用来记录程序每天的运行状况的,比如程序出现异常的情况,或是某个关键点,功某个重要的数据或交易等.这里的每天不是说每天一记,可以是伴随着程序运行的始终,只要程序在运行着就一直在记

搜集整理java中GC的理解

Java的垃圾回收机制是Java虚拟机提供的能力,用于在空闲时间以不定时的方式动态回收无任何引用的对象占据的内存空间. 需要注意的是:垃圾回收回收的是无任何引用的对象占据的内存空间而不是对象本身: System.gc() Runtime.getRuntime().gc() 上面的方法调用时用于显式通知JVM可以进行一次垃圾回收,但真正垃圾回收机制具体在什么时间点开始发生动作这同样是不 可预料的 ===================================================

Java中GC的工作原理

转文: 一个优秀的Java程序员必须了解GC的工作原理.如何优化GC的性能.如何与GC进行有限的交互,有一些应用程序对性能要求较高,例如嵌入式系统.实时系统等,只有全面提升内存的管理效率,才能提高整个应用程序的性能.本文将从GC的工作原理.GC的几个关键问题进行探讨,最后提出一些Java程序设计建议,如何从GC角度提高Java程序的性能. 一.GC的基本原理: GC是什么? 为什么要有GC呢? GC是垃圾收集的意思(Garbage Collection),内存处理是编程人员容易出现问题的地方,忘

浅谈Java中的System.gc()的工作原理

很多人把Java的“效率低下”归咎于不能自由管理内存,但我们也知道将内存管理封装起来的好处,这里就不赘述. Java中的内存分配是随着new一个新的对象来实现的,这个很简单,而且也还是有一些可以“改进”内存回收的机制的,其中最显眼的就是这个System.gc()函数. 乍一看这个函数似乎是可以进行垃圾回收的,可事实并不是那么简单.其实这个gc()函数的作用只是提醒虚拟机:程序员希望进行一次垃圾回收.但是它不能保证垃圾回收一定会进行,而且具体什么时候进行是取决于具体的虚拟机的,不同的虚拟机有不同的