JVM笔记

Java中对象一定分配在堆空间上吗?

逃逸分析:分析对象动态作用域,当一个对象在方法中被定义后,它可能被外部方法所引用,例如作为调用参数传递到其他地方中,称为方法逃逸。
在编译期间根据逃逸分析的结果,来决定是否可以将对象的内存分配从堆转化为栈。如果经过逃逸分析后发现,一个对象并没有逃逸出方法的话,那么就可能被优化成栈上分配。这样就无需在堆上分配内存,也无须进行垃圾回收了。

判断一个对象是否还活着

  1. 引用计数
  2. 可达性分析
    GC Root
    • 虚拟机栈中引用的对象
    • 方法区类静态属性引用的对象
    • 方法区常量池引用的对象
    • 本地方法栈JNI引用的对象
  3. 强引用,软,弱,虚
  4. 死亡二次标记
    不可达,判断该对象是否覆盖了finalize方法,若未覆盖,则直接将其回收。
    若对象未执行过finalize方法,将其放入F-Queue队列,由一低优先级线程执行该队列中对象的finalize方法。
    在finalize方法里将当前对象与 GC Roots 再次关联。若仍不可达,则进行回收

GC

在这里插入图片描述
新生代:老年代=1:2
新生代分为 Eden 和 两个 Survivor 区域,Edem :Survivor *2 = 8 : 1 : 1

新生代 Minor GC 复制清除 频繁
老年代 Full GC 标记清除 次数少,时间长,容易有碎片导致gc

当一个对象被判定为 “死亡” 的时候,
当对象在 Eden ( 包括一个 Survivor 区域,这里假设是 from 区域 ) 出生后,在经过一次 Minor GC 后,如果对象还存活,并且能够被另外一块 Survivor 区域所容纳( 上面已经假设为 from 区域,这里应为 to 区域,即 to 区域有足够的内存空间来存储 Eden 和 from 区域中存活的对象 ),则使用复制算法将这些仍然还存活的对象复制到另外一块 Survivor 区域 ( 即 to 区域 ) 中,然后清理所使用过的 Eden 以及 Survivor 区域 ( 即 from 区域 ),并且将这些对象的年龄设置为1,以后对象在 Survivor 区每熬过一次 Minor GC,就将对象的年龄 + 1,当对象的年龄达到某个值时 ( 默认是 15 岁,可以通过参数 -XX:MaxTenuringThreshold 来设定 ),这些对象就会成为老年代。
对于一些较大的对象 ( 即需要分配一块较大的连续内存空间 ) 则是直接进入到老年代。

gc频繁

Full GC次数过多,主要有以下两种原因:

  • 代码中一次获取了大量的对象,导致内存溢出;
  • 内存占用不高,但是Full GC次数还是比较多,此时可能是显示的 System.gc()调用导致GC次数过多,可以禁用JVM对显示GC的响应。
  • 堆栈日志+压测,查看日志
  • 多线程,死锁/多线程阻塞
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值