深入理解 Java 虚拟机 笔记 (2018.07.10-14) – 热爱改变生活
我的GitHub GitHub |     登录
  • If you can't fly, then run; if you can't run, then walk; if you can't walk, then crawl
  • but whatever you do, you have to keep moving forward。
  • “你骗得了我有什么用,这是你自己的人生”
  • 曾有伤心之地,入梦如听 此歌

深入理解 Java 虚拟机 笔记 (2018.07.10-14)

Code sinvader 534℃ 0评论

笔记书籍:《深入理解 Java 虚拟机》

笔记日期: 2018-07-10 一一 2018-07-14

GC 日志的解读

33.125 / 100.667 : GC 发生的时间 (虚拟机从启动以来的秒数)

[GC / [Full GC / [Full GC(system) : 这次垃圾收集的停顿类型, 如果是 Full, 那么这次 GC 中发生了 Stop-The-World System.gc

[DefNew / [Tenured : 表明了发生 GC 的区域, 也可以从中看出来收集器的类型, 如 DefNew 就是使用的 Serial 收集器

3324k->152k(11904k) : GC前该区域已使用的内存->GC 后该区域已使用的内存 (内存总容量)

内存分配策略

对象优先在 Eden 分配, 如果内存不够了就进行 Minor GC

如果限制 Java 堆为 20M, 新生代和老年代都为 10M, 新生代 Eden 和 Survivor 为 8:1, 那么 Eden 为 8M, 程序执行完成之后内存是如何分配的呢?

    allocation1 先进入到 Eden,allocation2 进入到 Eden, 空间还够,allocation3 进入到 Eden, 这时候 Eden 中已经放了 6M 了, 还剩下 2M 的空间,allocation4 已经放不进去了. 那就进行 GC 吧 (进行 MinorGC)
    GC 的时候发现 allocation1-3 都是存活的对象并且大小都大于 Survivor 的 1M, 所以只好通过担保机制将 allocation4 放到了老年代
    运行完成之后 Eden 放了三个 2M 的对象, 老年代放了一个 4M 的对象,Survivor 全是空的

注 : MinorGC 就是新生代 GC,MajorGC/FullGC 是老年代 GC

大对象直接进入到老年代

所谓的大对象, 指的是需要大量连续内存空间的 Java 对象, 比如说很长的字符串以及数组.(虚拟机很不喜欢的就是遇到一群” 朝生夕灭” 的” 大对象”, 尽量少用这样的对象)

可以通过 -XX:PretenureSizeThreshold 参数设置大于这个大小的对象直接进入到老年代

长期存活的对象进入老年代

虚拟机给每个对象定义了一个对象年龄计数器, 对象在 Eden 中创建并且如果能在 survivor 中存活, 每存活一次它的年龄都+1, 当它的年龄大于某个数值的时候 ( 默认是 15 ), 它就会进入到老年代中.

每次 GC 的时候 Eden 和其中一个 Survivor(称为 From) 会将还存活的对象复制到 To(另一个 Survivor) 中去, 然后直接将 Eden 和 From 给清空了, 下一次的时候 To 就会作为 From 继续此过程.

动态对象年龄判定

如果在 Survivor 空间中相同年龄所有对象的大小总和大于 Survivor 空间的一半, 年龄大于或等于该年龄的对象就可以直接进入到老年代.

空间分配担保

在发生 MinorGC 的时候, 是需要将 Eden(E)+Survivor(A) 中存活的对象复制到另一个 Survivor(B) 中的, 那么就有可能 B 中的空间不够存放 E+A, 这个时候就需要老年代的空间来担保, 担保的意思就是说如果你那里不够放下的话, 可以放到我这里来.

那么如果老年代中的连续的空间够 E+A 的存放, 那么这一次 GC 肯定是可以成功的.

如果老年代中的连续的空间不够了, 要去看虚拟机设置的参数 HandlePromotionFailure 了, 如果设置的是不允许担保失败, 那么只能进行 FullGC 了. 不过如果设置的是允许担保失败, 那么虚拟机就会进行一次风险 GC.

风险 GC 是这样执行的, 虚拟机会记录之前每次 GC 的时候进入到老年代中的对象的平均值大小, 如果现在老年代中的连续的内存的大小是大于进入到老年代对象的平均值大小的, 那么就可以尝试进行一次风险 GC.

如果这次风险 GC 中进入到老年代中对象的大小高于平均值, 那么老年代中肯定是放不下的, 那么只好进行一次 FullGC 了, 否则这次 GC 就会成功了.

但是 : 在 JDK1.6Update24 之后, 这个参数已经不再使用了, 也就是说如果老年代的连续空间大于新生代空间或者大于历次晋升的平均值, 那么就会进行一次 MinorGC, 否则会进行 FullGC

类文件结构

一些基础知识

Java 虚拟机不和包括 Java 在内的任何语言绑定, 它只与”Class 文件” 这种特定的二进制文件格式所关联, 而在 Class 文件中包含了 Java 虚拟机指令集和符号表以及若干其他的辅助信息.

任何一个 Class 文件都对应着唯一一个类或者接口的定义信息, 但是类或者接口不一定都得定义在文件里 (类或者接口也可以通过类加载器直接生成)

无符号数用来描述数字, 索引等信息, 通过 u1,u2,u4,u8 来描述. 描述的时候经常会使用一个前置的容量计数器加若干个连续的数据项的形式, 这时称这一系列连续的某一类型数据为某一类型的集合.

本周看的还未全部总结完成, 继续中…

¥ 有帮助么?打赏一下~

转载请注明:热爱改变生活.cn » 深入理解 Java 虚拟机 笔记 (2018.07.10-14)


本博客只要没有注明“转”,那么均为原创。 转载请注明链接:sumile.cn » 深入理解 Java 虚拟机 笔记 (2018.07.10-14)

喜欢 (0)
发表我的评论
取消评论
表情

如需邮件形式接收回复,请注册登录

Hi,你需要填写昵称和邮箱~

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址