Java垃圾回收

GC是什么?为什么要有GC? 答:GC是垃圾收集的意思,内存处理是编程人员容易出现问题的地方,忘记或者错误的内存回收会导致程序或系统的不稳定甚至崩溃,Java提供的GC功能可以自动监测对象是否超过作用域从而达到自动回收内存的目的,Java语言没有提供释放已分配内存的显示操作方法。Java程序员不用担心内存管理,因为垃圾收集器会自动进行管理。要请求垃圾收集,可以调用下面的方法之一:System.gc() 或Runtime.getRuntime().gc() ,但JVM可以屏蔽掉显示的垃圾回收调用。
垃圾回收可以有效的防止内存泄露,有效的使用可以使用的内存。垃圾回收器通常是作为一个单独的低优先级的线程运行,不可预知的情况下对内存堆中已经死亡的或者长时间没有使用的对象进行清除和回收,程序员不能实时的调用垃圾回收器对某个对象或所有对象进行垃圾回收。在Java诞生初期,垃圾回收是Java最大的亮点之一,因为服务器端的编程需要有效的防止内存泄露问题,然而时过境迁,如今Java的垃圾回收机制已经成为被诟病的东西。移动智能终端用户通常觉得iOS的系统比Android系统有更好的用户体验,其中一个深层次的原因就在于Android系统中垃圾回收的不可预知性。
补充:垃圾回收机制有很多种,包括:分代复制垃圾回收、标记垃圾回收、增量垃圾回收等方式。标准的Java进程既有栈又有堆。栈保存了原始型局部变量,堆保存了要创建的对象。Java平台对堆内存回收和再利用的基本算法被称为标记和清除,但是Java对其进行了改进,采用“分代式垃圾收集”。这种方法会跟Java对象的生命周期将堆内存划分为不同的区域,在垃圾收集过程中,可能会将对象移动到不同区域:

  • 伊甸园(Eden):这是对象最初诞生的区域,并且对大多数对象来说,这里是它们唯一存在过的区域。
  • 幸存者乐园(Survivor):从伊甸园幸存下来的对象会被挪到这里。
  • 终身颐养园(Tenured):这是足够老的幸存对象的归宿。年轻代收集(Minor-GC)过程是不会触及这个地方的。当年轻代收集不能把对象放进终身颐养园时,就会触发一次完全收集(Major-GC),这里可能还会牵扯到压缩,以便为大对象腾出足够的空间。
一个系统,定时任务超级多,但是每个定时任务都很短,在JVM优化上,应该怎么配置才能达到性能最优 把新生代的那块内存设置大一点..
s0和s1区交换区比例
Java垃圾回收
文章图片
如何确定垃圾?
  • 引用计数 ×
  • 从垃圾回收的根出发可见
垃圾回收根节点
  • 局部变量
  • 静态变量
  • Native方法所引用的对象
  • 活动线程,等待中的Monitor(wait,notify,synchronized)
现在jvm采用分代回收机制,简单来说就是分为新生代和老生代,老生代内存空间比新生代大;大部分新对象都会优先分配到新生代,当新生代空间满了会发起一次Minor GC。而新分配的大对象或者在新生代空间里存活很久的对象会被放到老生代里,老生代空间满了会发起Major GC,但由于老生代里的对象生命周期比较长加上Major GC速度比Minor GC慢很多,所以发生在老生代的Major GC相对会比Minor GC少很多。因此垃圾能不能被立即回收,要看垃圾的大小,它所处在的空间和当前所处空间是否已满才能基本确定。
Java分代垃圾回收算法 基础假设:大部分对象只存在很短的时间
将内存分为新生代,老生代
将新生代分为Eden,Survivor1,Survivor2
Java垃圾回收
文章图片
Java垃圾回收
文章图片
Java垃圾回收
文章图片
Java垃圾回收
文章图片
Java垃圾回收
文章图片
新生代中 存活一定次数会被转入老生代
Major/Full GC 会对老生代做GC
老生代GC采用Compact算法(标记、压缩)
参数配置:
  • -XX: NewRatio 老生代/新生代比例,默认2
  • -XX: SurvivorRatio Eden/Survivor比例,默认8
  • -XX: MaxTenuringThreshold 新生代转至老生代阈值,默认15
PermGen Space Permanent Generation 持久代
  • 放置ClassLoader读进来的Class,除系统Class外
  • 放置String.intern后的结果
  • 易出现OutOfMemoryError:PermGen Space
  • 使用 -XX: MaxPermSize调整
  • Java 1.8使用Metaspace,取消持久代
  • String.intern的结果被放入堆
  • Metaspace默认不设限制,使用系统内存
垃圾回收在什么时候运行? 内存分配失败时候,System.gc()
垃圾回收对什么对象进行回收? 从垃圾回收的根节点出发,顺着引用关系的对象去找,找不到的对象进行垃圾回收
垃圾回收算法对内存划分了哪些区域 新生代、老生代、持久代(MetaSpace),新生代又分为Eden,S1,S2
新生代采用了拷贝的方法,Eden+s -> s,存活时间久的话就放到老生代,
老生代采用的Compact算法,MetaSpace放一些class Object
垃圾回收的调试 获取信息
-verbose:gc
-XX:+HeapDumpOnOutOfMemoryError
-XX:+PrintGCDetails -Xloggc:
Spring Actuator
【Java垃圾回收】查看信息
官方: visualvm,jmap
Eclipse Memory Analyzer(MAT)
在线: gceasy.io fastthread.io

    推荐阅读