读《深入理解Java虚拟机》- 笔记01

《深入理解Java虚拟机:JVM高级特性与最佳实践》第2版

  1. 读这本书的原因之一:认识技术的本质,帮助思考“程序这样写好不好”,检查程序背后的漏洞(如并发问题)。

  2. 虚拟机配置参数:
    -Xms 最小/初始堆容量
    -Xmx 最大堆容量
    -Xmn 新生代大小
    (所以老生代大小为 Xmx-Xmn)
    -Xss 设置每个线程可使用的内存大小,也就是栈容量。
    -Xoss 设置本地方法栈大小无效(HotSpot虚拟机不区分虚拟机栈和本地方法栈)
    -XX 直接内存容量(如不指定,默认与Java堆最大值相同)

  3. NIO高性能的原因之一:使用Native函数库直接分配堆外内存,通过存在Java堆中的DirectByteBuffer对象作为堆外内存的引用进行操作。避免在Java堆和Native堆来回复制数据。

  4. Java堆内存分配算法:指针碰撞、空闲列表。
    Serial、ParNew收集器,有Compact过程,用的是指针碰撞;
    CMS收集器,基于Mark-Sweep算法,采用空闲列表。

  5. 对象头包含的信息有两部分:
    (1) 运行时数据:对象的哈希码、对象的GC分代年龄,锁状态标志、线程持有的锁,是否启用偏向锁等。
    (2) 类型指针: 对象是哪个类的实例、如何找到类的元数据信息(不一定有,why?)。

  6. 内存回收
    不需要回收的:程序计数器、虚拟机栈、本地方法栈(随线程自生自灭);
    需要考虑回收的:Java堆、方法区(动态创建、动态回收)。

  7. 主流JVM不采用引用计数法管理内存,存在循环引用问题;
    采用的是可达性分析。

  8. 方法区回收分为废弃常量(与对象回收类似)、废弃类。
    判断类可以回收(但不一定会回收)同时满足以下条件:
    (1) 类的所有实例已回收;
    (2) 类的ClassLoader已回收;
    (3) 类的Class 对象没有任何地方被引用,无法在任何地方通过反射访问类的方法。

  9. 分代收集
    新生代-复制算法(eden,survivor);老年代-标记清除 或者 标记整理。

  10. 发起垃圾回收
    用OopMap存放对象引用,方便GC直接扫描引用。但是OopMap会随指令变化而变化,为了生成稳定的OopMap,只在长时间执行的安全点或安全区域生成OopMap。

主动式中断:不直接对线程操作,而是设置一个标志,线程轮询标志,发现终端标志为真时,自己终端挂起,响应GC事件。

  1. 并发收集器:CMS(Concurrent Mark Sweep)收集器,垃圾回收与用户线程同时工作。多CPU实现并发。包含四步:初始标记、并发标记、重新标记、并发清除。

并行,多线程实现。

  1. CMS的初始标记:标记GC Roots直接关联的引用;
    并发标记:剩下能关联到的引用。

初始标记是去找所有的GC root对象(通常为常常量区的静态对象和java方法栈中的对象),并发标记是用多线程对每个GC root对象进行tracing搜索,就是在堆中查找其下所有能关联到的对象。所以第二阶段工作量非常大,使用并发方式可以大大加快GC时间。


未完待续...

你可能感兴趣的:(读《深入理解Java虚拟机》- 笔记01)